]>
cygwin.com Git - cygwin-apps/setup.git/blob - rsync/tube.c
1 /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*-
3 * librsync -- dynamic caching and delta update in HTTP
6 * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 | Where a calculator on the ENIAC is
25 | equpped with 18,000 vaccuum tubes and
26 | weighs 30 tons, computers in the
27 | future may have only 1,000 vaccuum
28 | tubes and perhaps weigh 1 1/2
30 | -- Popular Mechanics, March 1949
34 /* tube: a somewhat elastic but fairly small buffer for data passing
37 * In most cases the iter can adjust to send just as much data will
38 * fit. In some cases that would be too complicated, because it has
39 * to transmit an integer or something similar. So in that case we
40 * stick whatever won't fit into a small buffer.
42 * A tube can contain some literal data to go out (typically command
43 * bytes), and also an instruction to copy data from the stream's
44 * input or from some other location. Both literal data and a copy
45 * command can be queued at the same time, but only in that order and
46 * at most one of each. */
50 * TODO: As an optimization, write it directly to the stream if
51 * possible. But for simplicity don't do that yet.
53 * TODO: I think our current copy code will lock up if the application
54 * only ever calls us with either input or output buffers, and not
55 * both. So I guess in that case we might need to copy into some
56 * temporary buffer space, and then back out again later.
74 static void rs_tube_catchup_write(rs_job_t
*job
)
76 rs_buffers_t
*stream
= job
->stream
;
83 if ((size_t) len
> stream
->avail_out
)
84 len
= stream
->avail_out
;
86 if (!stream
->avail_out
) {
87 rs_trace("no output space available");
91 memcpy(stream
->next_out
, job
->write_buf
, len
);
92 stream
->next_out
+= len
;
93 stream
->avail_out
-= len
;
95 remain
= job
->write_len
- len
;
96 rs_trace("transmitted %d write bytes from tube, "
97 "%d remain to be sent",
101 /* Still something left in the tube... */
102 memmove(job
->write_buf
, job
->write_buf
+ len
, remain
);
107 job
->write_len
= remain
;
112 * Execute a copy command, taking data from the scoop.
114 * \sa rs_tube_catchup_copy()
117 rs_tube_copy_from_scoop(rs_job_t
*job
)
120 rs_buffers_t
*stream
= job
->stream
;
122 this_len
= job
->copy_len
;
123 if (this_len
> job
->scoop_avail
) {
124 this_len
= job
->scoop_avail
;
126 if (this_len
> stream
->avail_out
) {
127 this_len
= stream
->avail_out
;
130 memcpy(stream
->next_out
, job
->scoop_next
, this_len
);
132 stream
->next_out
+= this_len
;
133 stream
->avail_out
-= this_len
;
135 job
->scoop_avail
-= this_len
;
136 job
->scoop_next
+= this_len
;
138 job
->copy_len
-= this_len
;
140 rs_trace("caught up on %ld copied bytes from scoop, %ld remain there, "
141 "%ld remain to be copied",
142 (long) this_len
, (long) job
->scoop_avail
, (long) job
->copy_len
);
148 * Catch up on an outstanding copy command.
150 * Takes data from the scoop, and the input (in that order), and
151 * writes as much as will fit to the output, up to the limit of the
154 static void rs_tube_catchup_copy(rs_job_t
*job
)
156 rs_buffers_t
*stream
= job
->stream
;
158 assert(job
->write_len
== 0);
159 assert(job
->copy_len
> 0);
161 if (job
->scoop_avail
&& job
->copy_len
) {
162 /* there's still some data in the scoop, so we should use that. */
163 rs_tube_copy_from_scoop(job
);
169 this_copy
= rs_buffers_copy(stream
, job
->copy_len
);
171 job
->copy_len
-= this_copy
;
173 rs_trace("copied %.0f bytes from input buffer, %.0f remain to be copied",
174 (double) this_copy
, (double) job
->copy_len
);
180 * Put whatever will fit from the tube into the output of the stream.
181 * Return RS_DONE if the tube is now empty and ready to accept another
182 * command, RS_BLOCKED if there is still stuff waiting to go out.
184 int rs_tube_catchup(rs_job_t
*job
)
187 rs_tube_catchup_write(job
);
189 if (job
->write_len
) {
190 /* there is still write data queued, so we can't send
196 rs_tube_catchup_copy(job
);
199 if (job
->stream
->eof_in
&& !job
->stream
->avail_in
&& !job
->scoop_avail
) {
201 "reached end of file while copying literal data through buffers");
202 return RS_INPUT_ENDED
;
212 /* Check whether there is data in the tube waiting to go out. So if true
213 * this basically means that the previous command has finished doing all its
215 int rs_tube_is_idle(rs_job_t
const *job
)
217 return job
->write_len
== 0 && job
->copy_len
== 0;
222 * Queue up a request to copy through \p len bytes from the input to
223 * the output of the stream.
225 * The data is copied from the scoop (if there is anything there) or
226 * from the input, on the next call to rs_tube_write().
228 * We can only accept this request if there is no copy command already
231 /* TODO: Try to do the copy immediately, and return a result. Then,
232 * people can try to continue if possible. Is this really required?
233 * Callers can just go out and back in again after flushing the
235 void rs_tube_copy(rs_job_t
*job
, int len
)
237 assert(job
->copy_len
== 0);
245 * Push some data into the tube for storage. The tube's never
246 * supposed to get very big, so this will just pop loudly if you do
249 * We can't accept write data if there's already a copy command in the
250 * tube, because the write data comes out first.
253 rs_tube_write(rs_job_t
*job
, const void *buf
, size_t len
)
255 assert(job
->copy_len
== 0);
257 if (len
> sizeof(job
->write_buf
) - job
->write_len
) {
258 rs_fatal("tube popped when trying to write %ld bytes!",
262 memcpy(job
->write_buf
+ job
->write_len
, buf
, len
);
263 job
->write_len
+= len
;
This page took 0.050297 seconds and 5 git commands to generate.