Mercurial > dovecot > original-hg > dovecot-1.2
annotate src/lib/iobuffer.c @ 122:9b87ee7cc19f HEAD
If we're corked, try to buffer the data instead of immediately trying to
write it. But is less syscalls faster than memcpy()ing?..
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 02 Sep 2002 23:23:32 +0300 |
parents | a73e43fa20e0 |
children | 788d8536ee18 |
rev | line source |
---|---|
0 | 1 /* |
2 iobuffer.c : Input/output transmit buffer handling | |
3 | |
4 Copyright (c) 2002 Timo Sirainen | |
5 | |
6 Permission is hereby granted, free of charge, to any person obtaining | |
7 a copy of this software and associated documentation files (the | |
8 "Software"), to deal in the Software without restriction, including | |
9 without limitation the rights to use, copy, modify, merge, publish, | |
10 distribute, sublicense, and/or sell copies of the Software, and to | |
11 permit persons to whom the Software is furnished to do so, subject to | |
12 the following conditions: | |
13 | |
14 The above copyright notice and this permission notice shall be | |
15 included in all copies or substantial portions of the Software. | |
16 | |
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
20 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
21 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
22 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
23 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
24 */ | |
25 | |
26 #include "lib.h" | |
27 #include "ioloop.h" | |
28 #include "iobuffer.h" | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
29 #include "mmap-util.h" |
58
8aaa39e7aec8
sendfile() works now properly with 64bit off_t
Timo Sirainen <tss@iki.fi>
parents:
56
diff
changeset
|
30 #include "sendfile-util.h" |
0 | 31 #include "network.h" |
32 | |
33 #include <unistd.h> | |
34 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
35 static unsigned int mmap_pagesize = 0; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
36 static unsigned int mmap_pagemask = 0; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
37 |
0 | 38 IOBuffer *io_buffer_create(int fd, Pool pool, int priority, |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
39 unsigned int max_buffer_size) |
0 | 40 { |
41 IOBuffer *buf; | |
42 | |
43 i_assert(fd >= 0); | |
44 i_assert(pool != NULL); | |
45 | |
46 buf = p_new(pool, IOBuffer, 1); | |
47 buf->fd = fd; | |
48 buf->pool = pool; | |
49 buf->priority = priority; | |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
50 buf->max_buffer_size = max_buffer_size; |
0 | 51 return buf; |
52 } | |
53 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
54 IOBuffer *io_buffer_create_file(int fd, Pool pool, |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
55 unsigned int max_buffer_size) |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
56 { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
57 IOBuffer *buf; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
58 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
59 buf = io_buffer_create(fd, pool, IO_PRIORITY_DEFAULT, max_buffer_size); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
60 buf->file = TRUE; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
61 return buf; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
62 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
63 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
64 IOBuffer *io_buffer_create_mmap(int fd, Pool pool, unsigned int block_size, |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
65 uoff_t size) |
0 | 66 { |
67 IOBuffer *buf; | |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
68 off_t start_offset, stop_offset; |
0 | 69 |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
70 /* block size must be page aligned, and at least two pages long */ |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
71 if (mmap_pagesize == 0) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
72 mmap_pagesize = getpagesize(); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
73 mmap_pagemask = mmap_pagesize-1; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
74 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
75 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
76 if (block_size < mmap_pagesize*2) |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
77 block_size = mmap_pagesize*2; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
78 else if ((block_size & mmap_pagemask) != 0) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
79 block_size &= ~mmap_pagemask; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
80 block_size += mmap_pagesize; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
81 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
82 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
83 buf = io_buffer_create_file(fd, pool, block_size); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
84 buf->mmaped = TRUE; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
85 buf->receive = TRUE; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
86 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
87 /* set offsets */ |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
88 start_offset = lseek(fd, 0, SEEK_CUR); |
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
89 stop_offset = lseek(fd, 0, SEEK_END); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
90 |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
91 if (start_offset < 0 || stop_offset < 0) { |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
92 i_error("io_buffer_create_mmap(): lseek() failed: %m"); |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
93 buf->start_offset = buf->size = 0; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
94 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
95 |
92
a73e43fa20e0
warn if io_buffer_create_mmap() contains invalid size parameter
Timo Sirainen <tss@iki.fi>
parents:
84
diff
changeset
|
96 if (start_offset > stop_offset) |
a73e43fa20e0
warn if io_buffer_create_mmap() contains invalid size parameter
Timo Sirainen <tss@iki.fi>
parents:
84
diff
changeset
|
97 start_offset = stop_offset; |
a73e43fa20e0
warn if io_buffer_create_mmap() contains invalid size parameter
Timo Sirainen <tss@iki.fi>
parents:
84
diff
changeset
|
98 |
a73e43fa20e0
warn if io_buffer_create_mmap() contains invalid size parameter
Timo Sirainen <tss@iki.fi>
parents:
84
diff
changeset
|
99 if (size > (uoff_t) (stop_offset-start_offset)) { |
a73e43fa20e0
warn if io_buffer_create_mmap() contains invalid size parameter
Timo Sirainen <tss@iki.fi>
parents:
84
diff
changeset
|
100 i_warning("Trying to create IOBuffer with size %"UOFF_T_FORMAT |
a73e43fa20e0
warn if io_buffer_create_mmap() contains invalid size parameter
Timo Sirainen <tss@iki.fi>
parents:
84
diff
changeset
|
101 " but we have only %"UOFF_T_FORMAT" bytes available " |
a73e43fa20e0
warn if io_buffer_create_mmap() contains invalid size parameter
Timo Sirainen <tss@iki.fi>
parents:
84
diff
changeset
|
102 "in file", size, stop_offset-start_offset); |
a73e43fa20e0
warn if io_buffer_create_mmap() contains invalid size parameter
Timo Sirainen <tss@iki.fi>
parents:
84
diff
changeset
|
103 size = stop_offset-start_offset; |
a73e43fa20e0
warn if io_buffer_create_mmap() contains invalid size parameter
Timo Sirainen <tss@iki.fi>
parents:
84
diff
changeset
|
104 } |
a73e43fa20e0
warn if io_buffer_create_mmap() contains invalid size parameter
Timo Sirainen <tss@iki.fi>
parents:
84
diff
changeset
|
105 |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
106 buf->start_offset = start_offset; |
92
a73e43fa20e0
warn if io_buffer_create_mmap() contains invalid size parameter
Timo Sirainen <tss@iki.fi>
parents:
84
diff
changeset
|
107 buf->size = size > 0 ? size : stop_offset - start_offset; |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
108 |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
109 buf->skip = buf->pos = buf->start_offset; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
110 return buf; |
0 | 111 } |
112 | |
113 void io_buffer_destroy(IOBuffer *buf) | |
114 { | |
115 if (buf == NULL) | |
116 return; | |
117 | |
118 if (buf->io != NULL) | |
119 io_remove(buf->io); | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
120 if (buf->buffer != NULL) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
121 if (!buf->mmaped) |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
122 p_free(buf->pool, buf->buffer); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
123 else |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
124 (void)munmap(buf->buffer, buf->buffer_size); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
125 } |
0 | 126 p_free(buf->pool, buf); |
127 } | |
128 | |
129 void io_buffer_close(IOBuffer *buf) | |
130 { | |
131 if (buf == NULL) | |
132 return; | |
133 | |
134 buf->closed = TRUE; | |
135 } | |
136 | |
137 void io_buffer_reset(IOBuffer *buf) | |
138 { | |
139 buf->pos = buf->skip = buf->cr_lookup_pos = 0; | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
140 buf->last_cr = FALSE; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
141 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
142 if (buf->mmaped && buf->buffer != NULL) { |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
143 (void)munmap(buf->buffer, buf->buffer_size); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
144 buf->buffer = NULL; |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
145 buf->buffer_size = 0; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
146 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
147 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
148 buf->mmap_offset = buf->offset = 0; |
0 | 149 } |
150 | |
151 IOBuffer *io_buffer_set_pool(IOBuffer *buf, Pool pool) | |
152 { | |
153 IOBuffer *newbuf; | |
154 | |
155 i_assert(buf != NULL); | |
156 i_assert(pool != NULL); | |
157 | |
158 newbuf = p_new(pool, IOBuffer, 1); | |
159 memcpy(newbuf, buf, sizeof(IOBuffer)); | |
160 | |
161 newbuf->pool = pool; | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
162 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
163 if (!newbuf->mmaped) { |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
164 newbuf->buffer = p_malloc(pool, buf->buffer_size); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
165 memcpy(newbuf->buffer, buf->buffer + buf->skip, |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
166 buf->buffer_size - buf->skip); |
0 | 167 |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
168 newbuf->cr_lookup_pos -= newbuf->skip; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
169 newbuf->pos -= newbuf->skip; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
170 newbuf->skip = 0; |
0 | 171 |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
172 p_free(buf->pool, buf->buffer); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
173 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
174 |
0 | 175 p_free(buf->pool, buf); |
176 return newbuf; | |
177 } | |
178 | |
179 void io_buffer_set_max_size(IOBuffer *buf, unsigned int max_size) | |
180 { | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
181 i_assert(!buf->mmaped); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
182 |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
183 buf->max_buffer_size = max_size; |
0 | 184 } |
185 | |
186 void io_buffer_set_send_blocking(IOBuffer *buf, unsigned int max_size, | |
187 int timeout_msecs, TimeoutFunc timeout_func, | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
188 void *context) |
0 | 189 { |
190 i_assert(!buf->receive); | |
191 | |
192 buf->transmit = TRUE; | |
193 buf->timeout_msecs = timeout_msecs; | |
194 buf->timeout_func = timeout_func; | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
195 buf->timeout_context = context; |
0 | 196 buf->blocking = max_size > 0; |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
197 buf->max_buffer_size = max_size; |
0 | 198 } |
199 | |
200 static int my_write(int fd, const void *buf, unsigned int size) | |
201 { | |
202 int ret; | |
203 | |
204 i_assert(size <= INT_MAX); | |
205 | |
206 if (size == 0) | |
9
21c8e080150d
fixes, seems to be somewhat working now.
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
207 return 0; |
0 | 208 |
209 ret = write(fd, buf, size); | |
210 if (ret < 0 && (errno == EINTR || errno == EAGAIN)) | |
211 ret = 0; | |
212 | |
213 return ret; | |
214 } | |
215 | |
216 static void buf_send_real(IOBuffer *buf) | |
217 { | |
218 int ret; | |
219 | |
220 if (!buf->file) { | |
221 ret = net_transmit(buf->fd, buf->buffer + buf->skip, | |
222 buf->pos - buf->skip); | |
223 } else { | |
224 ret = my_write(buf->fd, buf->buffer + buf->skip, | |
225 buf->pos - buf->skip); | |
226 } | |
227 | |
228 if (ret < 0) { | |
229 buf->closed = TRUE; | |
230 } else { | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
231 buf->offset += ret; |
0 | 232 buf->skip += ret; |
233 if (buf->skip == buf->pos) { | |
234 /* everything sent */ | |
235 buf->skip = buf->pos = 0; | |
236 | |
237 /* call flush function */ | |
238 if (buf->flush_func != NULL) { | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
239 buf->flush_func(buf->flush_context, buf); |
0 | 240 buf->flush_func = NULL; |
241 | |
242 if (buf->corked) { | |
243 /* remove cork */ | |
244 net_set_cork(buf->fd, FALSE); | |
245 buf->corked = FALSE; | |
246 } | |
247 } | |
248 } | |
249 } | |
250 } | |
251 | |
252 static int buf_send(IOBuffer *buf) | |
253 { | |
254 buf_send_real(buf); | |
255 | |
256 if (buf->closed || buf->pos == 0) { | |
257 io_remove(buf->io); | |
258 buf->io = NULL; | |
259 return FALSE; | |
260 } | |
261 | |
262 return TRUE; | |
263 } | |
264 | |
265 typedef struct { | |
266 IOLoop ioloop; | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
267 IOBuffer *outbuf; |
0 | 268 |
269 const char *data; | |
270 unsigned int size; | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
271 IOBuffer *inbuf; |
0 | 272 |
273 int timeout; | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
274 } IOBufferBlockContext; |
0 | 275 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
276 static void block_loop_send(IOBufferBlockContext *ctx) |
0 | 277 { |
278 int ret; | |
279 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
280 if (ctx->outbuf->skip != ctx->outbuf->pos) { |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
281 buf_send_real(ctx->outbuf); |
0 | 282 } else { |
283 /* send the data */ | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
284 ret = !ctx->outbuf->file ? |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
285 net_transmit(ctx->outbuf->fd, ctx->data, ctx->size) : |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
286 my_write(ctx->outbuf->fd, ctx->data, ctx->size); |
0 | 287 |
288 if (ret < 0) { | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
289 ctx->outbuf->closed = TRUE; |
0 | 290 } else { |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
291 ctx->outbuf->offset += ret; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
292 ctx->data += ret; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
293 ctx->size -= ret; |
0 | 294 } |
295 } | |
296 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
297 if (ctx->outbuf->closed || ctx->size == 0) |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
298 io_loop_stop(ctx->ioloop); |
0 | 299 } |
300 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
301 static void block_loop_timeout(void *context, Timeout timeout __attr_unused__) |
0 | 302 { |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
303 IOBufferBlockContext *ctx = context; |
0 | 304 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
305 ctx->timeout = TRUE; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
306 io_loop_stop(ctx->ioloop); |
0 | 307 } |
308 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
309 static int io_buffer_ioloop(IOBuffer *buf, IOBufferBlockContext *ctx, |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
310 void (*send_func)(IOBufferBlockContext *ctx)) |
0 | 311 { |
312 Timeout to; | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
313 int save_errno; |
0 | 314 |
315 /* close old IO */ | |
316 if (buf->io != NULL) | |
317 io_remove(buf->io); | |
318 | |
319 /* create a new I/O loop */ | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
320 ctx->ioloop = io_loop_create(); |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
321 ctx->outbuf = buf; |
0 | 322 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
323 buf->io = io_add(buf->fd, IO_WRITE, (IOFunc) send_func, ctx); |
0 | 324 to = buf->timeout_msecs <= 0 ? NULL : |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
325 timeout_add(buf->timeout_msecs, block_loop_timeout, ctx); |
0 | 326 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
327 io_loop_run(ctx->ioloop); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
328 save_errno = errno; |
0 | 329 |
330 if (buf->corked) { | |
331 /* remove cork */ | |
332 net_set_cork(buf->fd, FALSE); | |
333 buf->corked = FALSE; | |
334 } | |
335 | |
336 if (buf->io != NULL) { | |
337 io_remove(buf->io); | |
338 buf->io = NULL; | |
339 } | |
340 | |
341 if (to != NULL) { | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
342 if (ctx->timeout && buf->timeout_func != NULL) { |
0 | 343 /* call user-given timeout function */ |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
344 buf->timeout_func(buf->timeout_context, to); |
0 | 345 } |
346 timeout_remove(to); | |
347 } | |
348 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
349 io_loop_destroy(ctx->ioloop); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
350 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
351 errno = save_errno; |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
352 return ctx->size > 0 ? -1 : 1; |
0 | 353 } |
354 | |
355 static int io_buffer_send_blocking(IOBuffer *buf, const void *data, | |
356 unsigned int size) | |
357 { | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
358 IOBufferBlockContext ctx; |
0 | 359 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
360 memset(&ctx, 0, sizeof(ctx)); |
0 | 361 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
362 ctx.data = data; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
363 ctx.size = size; |
0 | 364 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
365 return io_buffer_ioloop(buf, &ctx, block_loop_send); |
0 | 366 } |
367 | |
368 void io_buffer_cork(IOBuffer *buf) | |
369 { | |
370 i_assert(!buf->receive); | |
371 | |
122
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
372 if (!buf->file && !buf->corked) |
0 | 373 net_set_cork(buf->fd, TRUE); |
122
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
374 buf->corked = TRUE; |
0 | 375 } |
376 | |
377 static void buffer_alloc_more(IOBuffer *buf, unsigned int size) | |
378 { | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
379 i_assert(!buf->mmaped); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
380 |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
381 buf->buffer_size = buf->pos+size; |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
382 buf->buffer_size = |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
383 buf->buffer_size <= IO_BUFFER_MIN_SIZE ? IO_BUFFER_MIN_SIZE : |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
384 nearest_power(buf->buffer_size); |
0 | 385 |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
386 if (buf->max_buffer_size > 0 && buf->buffer_size > buf->max_buffer_size) |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
387 buf->buffer_size = buf->max_buffer_size; |
0 | 388 |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
389 buf->buffer = p_realloc(buf->pool, buf->buffer, buf->buffer_size); |
0 | 390 if (buf->buffer == NULL) { |
391 /* pool limit exceeded */ | |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
392 buf->pos = buf->buffer_size = 0; |
0 | 393 } |
394 } | |
395 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
396 static void io_buffer_compress(IOBuffer *buf) |
0 | 397 { |
398 memmove(buf->buffer, buf->buffer + buf->skip, | |
399 buf->pos - buf->skip); | |
400 buf->pos -= buf->skip; | |
401 | |
402 if (buf->skip > buf->cr_lookup_pos) | |
403 buf->cr_lookup_pos = 0; | |
404 else | |
405 buf->cr_lookup_pos -= buf->skip; | |
406 | |
407 buf->skip = 0; | |
408 } | |
409 | |
410 int io_buffer_send(IOBuffer *buf, const void *data, unsigned int size) | |
411 { | |
122
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
412 int i, corked, ret; |
0 | 413 |
414 i_assert(!buf->receive); | |
415 i_assert(data != NULL); | |
416 i_assert(size < INT_MAX); | |
417 buf->transmit = TRUE; | |
418 | |
419 if (buf->closed) | |
420 return -1; | |
421 | |
122
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
422 /* if we're corked, first try adding it to buffer. if it's larger |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
423 than the buffer, send it immediately. */ |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
424 corked = buf->corked; |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
425 for (i = 0; i < 2; i++) { |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
426 if (buf->pos == 0 && !corked) { |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
427 /* buffer is empty, try to send the data immediately */ |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
428 ret = buf->file ? my_write(buf->fd, data, size) : |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
429 net_transmit(buf->fd, data, size); |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
430 if (ret < 0) { |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
431 /* disconnected */ |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
432 buf->closed = TRUE; |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
433 return -1; |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
434 } |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
435 |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
436 buf->offset += ret; |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
437 data = (const char *) data + ret; |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
438 size -= ret; |
0 | 439 } |
440 | |
122
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
441 if (size == 0) { |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
442 /* all sent */ |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
443 return 1; |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
444 } |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
445 |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
446 if (io_buffer_get_space(buf, size) != NULL) |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
447 break; |
39 | 448 |
122
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
449 if (corked) |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
450 corked = FALSE; |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
451 else { |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
452 if (buf->blocking) { |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
453 /* if we don't have space, we block */ |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
454 return io_buffer_send_blocking(buf, data, size); |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
455 } |
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
456 return -2; |
0 | 457 } |
458 } | |
459 | |
460 /* add to buffer */ | |
461 memcpy(buf->buffer + buf->pos, data, size); | |
462 buf->pos += size; | |
463 | |
464 if (buf->io == NULL) { | |
465 buf->io = io_add_priority(buf->fd, buf->priority, IO_WRITE, | |
466 (IOFunc) buf_send, buf); | |
467 } | |
468 return 1; | |
469 } | |
470 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
471 static void block_loop_sendfile(IOBufferBlockContext *ctx) |
0 | 472 { |
473 int ret; | |
474 | |
56 | 475 i_assert(ctx->inbuf->offset < OFF_T_MAX); |
476 | |
58
8aaa39e7aec8
sendfile() works now properly with 64bit off_t
Timo Sirainen <tss@iki.fi>
parents:
56
diff
changeset
|
477 ret = safe_sendfile(ctx->outbuf->fd, ctx->inbuf->fd, |
8aaa39e7aec8
sendfile() works now properly with 64bit off_t
Timo Sirainen <tss@iki.fi>
parents:
56
diff
changeset
|
478 &ctx->inbuf->offset, ctx->size); |
0 | 479 if (ret < 0) { |
480 if (errno != EINTR && errno != EAGAIN) | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
481 ctx->outbuf->closed = TRUE; |
0 | 482 ret = 0; |
483 } | |
484 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
485 ctx->size -= ret; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
486 if (ctx->outbuf->closed || ctx->size == 0) |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
487 io_loop_stop(ctx->ioloop); |
0 | 488 } |
489 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
490 static int io_buffer_sendfile(IOBuffer *outbuf, IOBuffer *inbuf, |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
491 unsigned int size) |
0 | 492 { |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
493 IOBufferBlockContext ctx; |
0 | 494 int ret; |
495 | |
56 | 496 i_assert(inbuf->offset < OFF_T_MAX); |
497 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
498 io_buffer_send_flush(outbuf); |
0 | 499 |
500 /* first try if we can do it with a single sendfile() call */ | |
58
8aaa39e7aec8
sendfile() works now properly with 64bit off_t
Timo Sirainen <tss@iki.fi>
parents:
56
diff
changeset
|
501 ret = safe_sendfile(outbuf->fd, inbuf->fd, &inbuf->offset, size); |
0 | 502 if (ret < 0) { |
503 if (errno != EINTR && errno != EAGAIN) | |
504 return -1; | |
505 ret = 0; | |
506 } | |
507 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
508 if ((unsigned int) ret == size) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
509 /* yes, all sent */ |
0 | 510 return 1; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
511 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
512 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
513 memset(&ctx, 0, sizeof(ctx)); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
514 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
515 ctx.inbuf = inbuf; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
516 ctx.size = size - ret; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
517 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
518 ret = io_buffer_ioloop(outbuf, &ctx, block_loop_sendfile); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
519 if (ret < 0 && errno == EINVAL) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
520 /* this shouldn't happen, must be a bug. It would also |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
521 mess up later if we let this pass. */ |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
522 i_fatal("io_buffer_sendfile() failed: %m"); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
523 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
524 return ret; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
525 } |
0 | 526 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
527 static void block_loop_copy(IOBufferBlockContext *ctx) |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
528 { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
529 unsigned char *in_data; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
530 unsigned int size; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
531 int ret; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
532 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
533 while ((ret = io_buffer_read_data(ctx->inbuf, &in_data, |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
534 &size, 0)) <= 0) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
535 if (ret == -1) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
536 /* disconnected */ |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
537 ctx->outbuf->closed = TRUE; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
538 break; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
539 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
540 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
541 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
542 /* send the data */ |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
543 ctx->data = (const char *) in_data; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
544 ctx->size = size; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
545 block_loop_send(ctx); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
546 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
547 io_buffer_skip(ctx->inbuf, size - ctx->size); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
548 } |
0 | 549 |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
550 int io_buffer_send_buf(IOBuffer *outbuf, IOBuffer *inbuf, unsigned int size) |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
551 { |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
552 IOBufferBlockContext ctx; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
553 unsigned char *in_data; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
554 unsigned int in_size; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
555 int ret; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
556 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
557 i_assert(size < INT_MAX); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
558 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
559 ret = io_buffer_sendfile(outbuf, inbuf, size); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
560 if (ret >= 0 || errno != EINVAL) |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
561 return ret; |
0 | 562 |
58
8aaa39e7aec8
sendfile() works now properly with 64bit off_t
Timo Sirainen <tss@iki.fi>
parents:
56
diff
changeset
|
563 /* sendfile() not supported (with this fd), fallback to |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
564 regular sending */ |
58
8aaa39e7aec8
sendfile() works now properly with 64bit off_t
Timo Sirainen <tss@iki.fi>
parents:
56
diff
changeset
|
565 |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
566 /* see if we can do it at one go */ |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
567 ret = io_buffer_read_data(inbuf, &in_data, &in_size, 0); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
568 if (ret == -1) |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
569 return -1; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
570 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
571 ret = !outbuf->file ? |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
572 net_transmit(outbuf->fd, in_data, in_size) : |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
573 my_write(outbuf->fd, in_data, in_size); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
574 if (ret < 0) |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
575 return -1; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
576 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
577 outbuf->offset += ret; |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
578 io_buffer_skip(inbuf, (unsigned int)ret); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
579 if ((unsigned int) ret == size) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
580 /* all sent */ |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
581 return 1; |
0 | 582 } |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
583 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
584 /* create blocking send loop */ |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
585 memset(&ctx, 0, sizeof(ctx)); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
586 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
587 ctx.inbuf = inbuf; |
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
588 ctx.size = size; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
589 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
590 return io_buffer_ioloop(outbuf, &ctx, block_loop_copy); |
0 | 591 } |
592 | |
593 void io_buffer_send_flush(IOBuffer *buf) | |
594 { | |
595 i_assert(!buf->receive); | |
596 | |
597 if (buf->closed || buf->io == NULL) | |
598 return; | |
599 | |
600 if (buf->skip != buf->pos) | |
601 io_buffer_send_blocking(buf, NULL, 0); | |
602 } | |
603 | |
604 void io_buffer_send_flush_callback(IOBuffer *buf, IOBufferFlushFunc func, | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
605 void *context) |
0 | 606 { |
607 i_assert(!buf->receive); | |
608 | |
609 if (buf->skip == buf->pos) { | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
610 func(context, buf); |
0 | 611 return; |
612 } | |
613 | |
614 buf->flush_func = func; | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
9
diff
changeset
|
615 buf->flush_context = context; |
0 | 616 } |
617 | |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
618 static int io_buffer_read_mmaped(IOBuffer *buf, unsigned int size) |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
619 { |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
620 uoff_t stop_offset; |
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
621 unsigned int aligned_skip; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
622 |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
623 stop_offset = buf->start_offset + buf->size; |
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
624 if (stop_offset - buf->mmap_offset <= buf->buffer_size) { |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
625 /* end of file is already mapped */ |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
626 return -1; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
627 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
628 |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
629 aligned_skip = buf->skip & ~mmap_pagemask; |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
630 if (aligned_skip == 0 && buf->buffer != NULL) { |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
631 /* didn't skip enough bytes */ |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
632 return -2; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
633 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
634 |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
635 buf->skip -= aligned_skip; |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
636 buf->mmap_offset += aligned_skip; |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
637 |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
638 if (buf->buffer != NULL) |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
639 (void)munmap(buf->buffer, buf->buffer_size); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
640 |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
641 buf->buffer_size = stop_offset - buf->mmap_offset; |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
642 if (buf->buffer_size > buf->max_buffer_size) |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
643 buf->buffer_size = buf->max_buffer_size; |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
644 if (buf->buffer_size > size) |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
645 buf->buffer_size = size; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
646 |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
647 buf->buffer = mmap(NULL, buf->buffer_size, PROT_READ, MAP_PRIVATE, |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
648 buf->fd, buf->mmap_offset); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
649 if (buf->buffer == MAP_FAILED) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
650 i_error("io_buffer_read_mmaped(): mmap() failed: %m"); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
651 return -1; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
652 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
653 |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
654 (void)madvise(buf->buffer, buf->buffer_size, MADV_SEQUENTIAL); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
655 |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
656 buf->pos = buf->buffer_size; |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
657 return buf->buffer_size; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
658 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
659 |
0 | 660 int io_buffer_read_max(IOBuffer *buf, unsigned int size) |
661 { | |
662 int ret; | |
663 | |
664 i_assert(size <= INT_MAX || size == UINT_MAX); | |
665 i_assert(!buf->transmit); | |
666 buf->receive = TRUE; | |
667 | |
668 if (buf->closed) | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
669 return -1; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
670 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
671 if (buf->mmaped) |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
672 return io_buffer_read_mmaped(buf, size); |
0 | 673 |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
674 if (buf->pos == buf->buffer_size) { |
0 | 675 if (buf->skip > 0) { |
676 /* remove the unused bytes from beginning of buffer */ | |
677 io_buffer_compress(buf); | |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
678 } else if (buf->max_buffer_size == 0 || |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
679 buf->buffer_size < buf->max_buffer_size) { |
0 | 680 /* buffer is full - grow it */ |
681 buffer_alloc_more(buf, IO_BUFFER_MIN_SIZE); | |
682 } | |
683 | |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
684 if (buf->pos == buf->buffer_size) |
0 | 685 return -2; /* buffer full */ |
686 } | |
687 | |
688 /* fill the buffer */ | |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
689 if (buf->buffer_size-buf->pos < size) |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
690 size = buf->buffer_size - buf->pos; |
0 | 691 |
692 if (!buf->file) { | |
693 ret = net_receive(buf->fd, buf->buffer + buf->pos, | |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
694 buf->buffer_size - buf->pos); |
0 | 695 } else { |
696 ret = read(buf->fd, buf->buffer + buf->pos, | |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
697 buf->buffer_size - buf->pos); |
0 | 698 if (ret == 0) |
699 ret = -1; /* EOF */ | |
700 else if (ret < 0 && (errno == EINTR || errno == EAGAIN)) | |
701 ret = 0; | |
702 } | |
703 | |
704 if (ret < 0) { | |
705 /* disconnected */ | |
706 return -1; | |
707 } | |
708 | |
709 buf->pos += ret; | |
710 return ret; | |
711 } | |
712 | |
713 int io_buffer_read(IOBuffer *buf) | |
714 { | |
715 return io_buffer_read_max(buf, UINT_MAX); | |
716 } | |
717 | |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
718 void io_buffer_skip(IOBuffer *buf, uoff_t size) |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
719 { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
720 int ret; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
721 |
9
21c8e080150d
fixes, seems to be somewhat working now.
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
722 buf->offset += size; |
21c8e080150d
fixes, seems to be somewhat working now.
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
723 |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
724 if (size <= buf->pos - buf->skip) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
725 buf->skip += size; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
726 return; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
727 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
728 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
729 if (buf->mmaped) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
730 /* these point outside mmap now, next io_buffer_read_mmaped() |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
731 will fix them */ |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
732 buf->skip += size; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
733 buf->pos = buf->skip; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
734 } else { |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
735 if (buf->buffer_size == 0) |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
736 buffer_alloc_more(buf, IO_BUFFER_MIN_SIZE); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
737 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
738 size -= buf->skip; |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
739 while (size > buf->buffer_size) { |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
740 ret = io_buffer_read_max(buf, buf->buffer_size); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
741 if (ret <= 0) |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
742 break; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
743 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
744 size -= ret; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
745 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
746 |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
747 (void)io_buffer_read_max(buf, (unsigned int)size); |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
748 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
749 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
750 |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
751 int io_buffer_seek(IOBuffer *buf, uoff_t offset) |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
752 { |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
753 uoff_t real_offset; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
754 |
75
7418fefb57a8
IOBuffer was buggy if start_offset wasn't 0
Timo Sirainen <tss@iki.fi>
parents:
63
diff
changeset
|
755 real_offset = buf->start_offset + offset; |
7418fefb57a8
IOBuffer was buggy if start_offset wasn't 0
Timo Sirainen <tss@iki.fi>
parents:
63
diff
changeset
|
756 if (real_offset > OFF_T_MAX) { |
7418fefb57a8
IOBuffer was buggy if start_offset wasn't 0
Timo Sirainen <tss@iki.fi>
parents:
63
diff
changeset
|
757 errno = EINVAL; |
7418fefb57a8
IOBuffer was buggy if start_offset wasn't 0
Timo Sirainen <tss@iki.fi>
parents:
63
diff
changeset
|
758 return FALSE; |
7418fefb57a8
IOBuffer was buggy if start_offset wasn't 0
Timo Sirainen <tss@iki.fi>
parents:
63
diff
changeset
|
759 } |
7418fefb57a8
IOBuffer was buggy if start_offset wasn't 0
Timo Sirainen <tss@iki.fi>
parents:
63
diff
changeset
|
760 |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
761 if (buf->mmaped) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
762 /* first reset everything */ |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
763 io_buffer_reset(buf); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
764 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
765 /* then set the wanted position, next read will |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
766 pick up from there */ |
75
7418fefb57a8
IOBuffer was buggy if start_offset wasn't 0
Timo Sirainen <tss@iki.fi>
parents:
63
diff
changeset
|
767 buf->pos = buf->skip = real_offset; |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
768 } else { |
50
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
769 if (lseek(buf->fd, (off_t)real_offset, SEEK_SET) != |
d493b9cc265e
Introduced uoff_t which is the unsigned-equilevant of off_t. This was needed
Timo Sirainen <tss@iki.fi>
parents:
39
diff
changeset
|
770 (off_t)real_offset) |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
771 return FALSE; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
772 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
773 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
774 buf->offset = offset; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
775 return TRUE; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
776 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
777 |
0 | 778 /* skip the first LF, if it exists */ |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
779 static void io_buffer_skip_lf(IOBuffer *buf) |
0 | 780 { |
781 if (!buf->last_cr || buf->skip >= buf->pos) | |
782 return; | |
783 | |
784 if (buf->buffer[buf->skip] == 10) { | |
785 if (buf->skip == buf->cr_lookup_pos) | |
786 buf->cr_lookup_pos++; | |
787 buf->skip++; | |
9
21c8e080150d
fixes, seems to be somewhat working now.
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
788 buf->offset++; |
0 | 789 } |
790 buf->last_cr = FALSE; | |
791 } | |
792 | |
793 char *io_buffer_next_line(IOBuffer *buf) | |
794 { | |
9
21c8e080150d
fixes, seems to be somewhat working now.
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
795 /* FIXME: buf->offset isn't updated right.. (skip_lf thing?) */ |
0 | 796 unsigned char *ret_buf; |
797 unsigned int i; | |
798 | |
799 i_assert(buf != NULL); | |
800 | |
801 io_buffer_skip_lf(buf); | |
802 if (buf->skip >= buf->pos) | |
803 return NULL; | |
804 | |
805 ret_buf = NULL; | |
806 for (i = buf->cr_lookup_pos; i < buf->pos; i++) { | |
807 if (buf->buffer[i] == 13 || buf->buffer[i] == 10) { | |
808 /* got it */ | |
809 buf->last_cr = buf->buffer[i] == 13; | |
810 buf->buffer[i] = '\0'; | |
811 ret_buf = buf->buffer + buf->skip; | |
812 | |
813 i++; | |
9
21c8e080150d
fixes, seems to be somewhat working now.
Timo Sirainen <tss@iki.fi>
parents:
5
diff
changeset
|
814 buf->offset += i - buf->skip; |
0 | 815 buf->skip = i; |
816 break; | |
817 } | |
818 } | |
819 | |
820 buf->cr_lookup_pos = i; | |
63 | 821 return ret_buf; |
0 | 822 } |
823 | |
824 unsigned char *io_buffer_get_data(IOBuffer *buf, unsigned int *size) | |
825 { | |
826 io_buffer_skip_lf(buf); | |
827 | |
828 if (buf->skip >= buf->pos) { | |
829 *size = 0; | |
830 return NULL; | |
831 } | |
832 | |
833 *size = buf->pos - buf->skip; | |
834 return buf->buffer + buf->skip; | |
835 } | |
836 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
837 int io_buffer_read_data(IOBuffer *buf, unsigned char **data, |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
838 unsigned int *size, unsigned int threshold) |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
839 { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
840 int ret; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
841 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
842 if (buf->pos - buf->skip <= threshold) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
843 /* we need more data */ |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
844 ret = io_buffer_read(buf); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
845 if (ret <= 0) { |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
846 *size = 0; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
847 *data = NULL; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
848 return ret; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
849 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
850 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
851 |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
852 *data = io_buffer_get_data(buf, size); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
853 return 1; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
854 } |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
855 |
0 | 856 unsigned char *io_buffer_get_space(IOBuffer *buf, unsigned int size) |
857 { | |
39 | 858 i_assert(size > 0); |
0 | 859 i_assert(size <= INT_MAX); |
860 i_assert(!buf->receive); | |
861 buf->transmit = TRUE; | |
862 | |
863 /* make sure we have enough space in buffer */ | |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
864 if (buf->buffer_size - buf->pos < size && buf->skip > 0) { |
0 | 865 /* remove the unused bytes from beginning of buffer */ |
866 io_buffer_compress(buf); | |
867 } | |
868 | |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
869 if (buf->buffer_size - buf->pos < size && |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
870 (buf->max_buffer_size == 0 || |
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
871 size <= buf->max_buffer_size - buf->pos)) { |
0 | 872 /* allocate more space */ |
873 buffer_alloc_more(buf, size); | |
874 } | |
875 | |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
876 if (buf->buffer_size - buf->pos < size) |
0 | 877 return NULL; |
878 | |
879 return buf->buffer + buf->pos; | |
880 } | |
881 | |
882 int io_buffer_send_buffer(IOBuffer *buf, unsigned int size) | |
883 { | |
884 int ret; | |
885 | |
886 i_assert(size <= INT_MAX); | |
887 i_assert(!buf->receive); | |
888 | |
122
9b87ee7cc19f
If we're corked, try to buffer the data instead of immediately trying to
Timo Sirainen <tss@iki.fi>
parents:
92
diff
changeset
|
889 if (buf->pos == 0 && !buf->corked) { |
0 | 890 /* buffer is empty, try to send the data immediately */ |
891 ret = buf->file ? my_write(buf->fd, buf->buffer, size) : | |
892 net_transmit(buf->fd, buf->buffer, size); | |
893 if (ret < 0) { | |
894 /* disconnected */ | |
895 buf->closed = TRUE; | |
896 return -1; | |
897 } | |
898 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
899 buf->offset += ret; |
0 | 900 if ((unsigned int) ret == size) { |
901 /* all sent */ | |
902 return 1; | |
903 } | |
904 | |
905 buf->skip += ret; | |
906 } | |
907 | |
908 buf->pos += size; | |
909 | |
910 if (buf->io == NULL) { | |
911 buf->io = io_add_priority(buf->fd, buf->priority, IO_WRITE, | |
912 (IOFunc) buf_send, buf); | |
913 } | |
914 | |
915 return 1; | |
916 } | |
917 | |
918 int io_buffer_set_data(IOBuffer *buf, const void *data, unsigned int size) | |
919 { | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
920 i_assert(!buf->mmaped); |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
921 |
0 | 922 io_buffer_reset(buf); |
923 | |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
924 if (buf->buffer_size < size) { |
0 | 925 buffer_alloc_more(buf, size); |
22
a946ce1f09b7
mbox fixes, not fully working yet but almost :)
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
926 if (buf->buffer_size < size) |
0 | 927 return -2; |
928 } | |
929 | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
930 buf->offset += size; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
931 buf->offset -= buf->pos - buf->skip; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
932 |
0 | 933 memcpy(buf->buffer, data, size); |
934 buf->pos = size; | |
5
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
935 buf->skip = 0; |
1b34ec11fff8
Message data is parsed in blocks (no longer entirely mmap()ed). Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
936 return 1; |
0 | 937 } |
938 | |
939 int io_buffer_is_empty(IOBuffer *buf) | |
940 { | |
941 return buf->skip >= buf->pos; | |
942 } |