chiark / gitweb /
From Peter Maydell (/u2/pmaydell/iwjbackup/) as per <E156bwm-0005xq-00@watchdragon...
[chiark-utils.git] / backup / Ucam.comp.unix
1 From ijackson@chiark.greenend.org.uk Wed Aug 12 19:36:07 BST 1998
2 Article: 742 of ucam.comp.unix
3 Path: ewrotcd!not-for-mail
4 From: ijackson@chiark.greenend.org.uk (Ian Jackson)
5 Newsgroups: ucam.comp.unix,comp.sys.sun.admin
6 Subject: Buffering programs (was Re: Speeding up network dumps)
7 Date: 21 Jul 1998 12:23:23 +0100 (BST)
8 Organization: Linux Unlimited
9 Lines: 233
10 Message-ID: <xWb*k6rBn@news.chiark.greenend.org.uk>
11 References: <6oiapl$6k5$1@pegasus.csx.cam.ac.uk> <6ol7kf$cln$2@pegasus.csx.cam.ac.uk>
12 NNTP-Posting-Host: chiark.greenend.org.uk
13 X-Server-Date: 21 Jul 1998 11:23:25 GMT
14 Originator: ijackson@news.chiark.greenend.org.uk ([127.0.0.1])
15 Xref: news.chiark.greenend.org.uk ucam.comp.unix:742 comp.sys.sun.admin:14526
16
17 I said I'd post here the buffering programs that I use, so here they
18 are.
19
20 They're perfectly functional and (I believe) correct, but they do lack
21 sophistication.  The size of the buffer is a #define, and the
22 diagnostics lack verbosity.  I haven't compiled them on anything but
23 Linux/i386 libc5, but they ought to work on other reasonable Unices.
24
25 writebuffer is intended for writing to tapes; when its buffer is empty
26 it will write no more data until it gets 3/4 of its buffer filled, or
27 EOF.
28
29 readbuffer is intended for reading from tapes; when its buffer becomes
30 full it stops reading until it's down to 1/4.
31
32 Remember that using shell pipes loses the exit status of all but the
33 last command, and so can cause failures to go unnoticed.
34
35
36 /*
37  * writebuffer.c
38  *
39  * Copyright (C) 1997,1998 Ian Jackson <ian@chiark.greenend.org.uk>
40  *
41  * This is free software; you can redistribute it and/or modify
42  * it under the terms of the GNU General Public License as
43  * published by the Free Software Foundation; either version 2,
44  * or (at your option) any later version.
45  *
46  * This is distributed in the hope that it will be useful, but
47  * WITHOUT ANY WARRANTY; without even the implied warranty of
48  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
49  * GNU General Public License for more details.
50  *
51  * You should have received a copy of the GNU General Public
52  * License along with this file; if not, write to the Free Software
53  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
54  *
55  */
56
57 #include <sys/time.h>
58 #include <sys/types.h>
59 #include <fcntl.h>
60 #include <stdio.h>
61 #include <errno.h>
62 #include <unistd.h>
63
64 #define BUFFER 16*1024*1024
65 #define WAITFILL ((BUFFER*3)/4)
66
67 static inline int min(int a, int b) { return a<=b ? a : b; }
68
69 static void nonblock(int fd) {
70   int r;
71   r= fcntl(fd,F_GETFL,0); if (r == -1) { perror("fcntl getfl"); exit(1); }
72   r |= O_NDELAY;
73   if (fcntl(fd,F_SETFL,r) == -1) { perror("fcntl setfl"); exit(1); }
74 }
75
76 int main(void) {
77   static unsigned char buf[BUFFER];
78   
79   unsigned char *wp, *rp;
80   int used,r,writing,seeneof;
81   fd_set readfds;
82   fd_set writefds;
83
84   used=0; wp=rp=buf; writing=0; seeneof=0;
85   nonblock(0); nonblock(1);
86   while (!seeneof || used) {
87     FD_ZERO(&readfds); if (!seeneof && used+1<BUFFER) FD_SET(0,&readfds);
88     FD_ZERO(&writefds); if (writing) FD_SET(1,&writefds);
89 /*fprintf(stderr,"used %6d writing %d seeneof %d wp %8lx rp %8lx read %d write %d\n",
90         used,writing,seeneof,(unsigned long)(wp-buf),(unsigned long)(rp-buf),
91         FD_ISSET(0,&readfds),FD_ISSET(1,&writefds));*/
92     r= select(2,&readfds,&writefds,0,0);
93 /*fprintf(stderr,"\t readable %d writeable %d\n",
94         FD_ISSET(0,&readfds),FD_ISSET(1,&writefds));*/
95     if (r == -1) {
96       if (errno == EINTR) continue;
97       perror("select"); exit(1);
98     }
99     if (FD_ISSET(1,&writefds) && !FD_ISSET(0,&readfds) && !used) {
100       writing= 0;
101       FD_CLR(1,&writefds);
102 /*fprintf(stderr,"\t buffers empty - stopping\n");*/
103     }
104     if (FD_ISSET(0,&readfds)) {
105       r= read(0,rp,min(BUFFER-1-used,buf+BUFFER-rp));
106       if (!r) {
107 /*fprintf(stderr,"\t eof detected\n");*/
108         seeneof=1; writing=1;
109       } else if (r<0) {
110         if (!(errno == EAGAIN || errno == EINTR)) { perror("read"); exit(1); }
111 fprintf(stderr,"\t read transient error\n");
112       } else {
113 /*fprintf(stderr,"\t read %d\n",r);*/
114         used+= r;
115         rp+= r;
116         if (rp == buf+BUFFER) rp=buf;
117 /*fprintf(stderr,"\t starting writes\n");*/
118       }
119       if (used > WAITFILL) writing=1;
120     }
121     if (FD_ISSET(1,&writefds) && used) {
122       r= write(1,wp,min(used,buf+BUFFER-wp));
123       if (r<=0) {
124         if (!(errno == EAGAIN || errno == EINTR)) { perror("write"); exit(1); }
125 /*fprintf(stderr,"\t write transient error\n");*/
126       } else {
127 /*fprintf(stderr,"\t wrote %d\n",r);*/
128         used-= r;
129         wp+= r;
130         if (wp == buf+BUFFER) wp=buf;
131       }
132     }
133   }
134   exit(0);
135 }
136
137
138 /*
139  * readbuffer.c
140  *
141  * Copyright (C) 1997,1998 Ian Jackson <ian@chiark.greenend.org.uk>
142  *
143  * This is free software; you can redistribute it and/or modify
144  * it under the terms of the GNU General Public License as
145  * published by the Free Software Foundation; either version 2,
146  * or (at your option) any later version.
147  *
148  * This is distributed in the hope that it will be useful, but
149  * WITHOUT ANY WARRANTY; without even the implied warranty of
150  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
151  * GNU General Public License for more details.
152  *
153  * You should have received a copy of the GNU General Public
154  * License along with this file; if not, write to the Free Software
155  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
156  *
157  */
158
159 #include <sys/time.h>
160 #include <sys/types.h>
161 #include <assert.h>
162 #include <fcntl.h>
163 #include <stdio.h>
164 #include <errno.h>
165 #include <unistd.h>
166
167 #define BUFFER 16*1024*1024
168 #define WAITEMPTY ((BUFFER*1)/4)
169
170 static inline int min(int a, int b) { return a<=b ? a : b; }
171
172 static void nonblock(int fd) {
173   int r;
174   r= fcntl(fd,F_GETFL,0); if (r == -1) { perror("fcntl getfl"); exit(1); }
175   r |= O_NDELAY;
176   if (fcntl(fd,F_SETFL,r) == -1) { perror("fcntl setfl"); exit(1); }
177 }
178
179 int main(void) {
180   static unsigned char buf[BUFFER];
181   
182   unsigned char *wp, *rp;
183   int used,r,reading,seeneof;
184   fd_set readfds;
185   fd_set writefds;
186
187   used=0; wp=rp=buf; reading=1; seeneof=0;
188   nonblock(0); nonblock(1);
189   while (!seeneof || used) {
190     FD_ZERO(&readfds);
191     if (reading) {
192       if (used<BUFFER-1) {
193         FD_SET(0,&readfds);
194       } else {
195 /*fprintf(stderr,"\t buffers full - stopping\n");*/
196         reading=0;
197       }
198     }
199     FD_ZERO(&writefds); if (used) FD_SET(1,&writefds);
200 /*fprintf(stderr,"used %6d reading %d seeneof %d wp %8lx rp %8lx read %d write %d\n",
201         used,reading,seeneof,(unsigned long)(wp-buf),(unsigned long)(rp-buf),
202         FD_ISSET(0,&readfds),FD_ISSET(1,&writefds));*/
203     r= select(2,&readfds,&writefds,0,0);
204 /*fprintf(stderr,"\t readable %d writeable %d\n",
205         FD_ISSET(0,&readfds),FD_ISSET(1,&writefds));*/
206     if (r == -1) {
207       if (errno == EINTR) continue;
208       perror("select"); exit(1);
209     }
210     if (FD_ISSET(0,&readfds)) {
211       r= read(0,rp,min(BUFFER-1-used,buf+BUFFER-rp));
212       if (!r) {
213 /*fprintf(stderr,"\t eof detected\n");*/
214         seeneof=1; reading=0;
215       } else if (r<0) {
216         if (!(errno == EAGAIN || errno == EINTR)) { perror("read"); exit(1); }
217 /*fprintf(stderr,"\t read transient error\n");*/
218       } else {
219 /*fprintf(stderr,"\t read %d\n",r);*/
220         used+= r;
221         rp+= r;
222         if (rp == buf+BUFFER) rp=buf;
223       }
224     }
225     if (FD_ISSET(1,&writefds)) {
226       assert(used);
227       r= write(1,wp,min(used,buf+BUFFER-wp));
228       if (r<=0) {
229         if (!(errno == EAGAIN || errno == EINTR)) { perror("write"); exit(1); }
230 /*fprintf(stderr,"\t write transient error\n");*/
231       } else {
232 /*fprintf(stderr,"\t wrote %d\n",r);*/
233         used-= r;
234         wp+= r;
235         if (wp == buf+BUFFER) wp=buf;
236       }
237       if (used < WAITEMPTY && !seeneof) {
238 /*fprintf(stderr,"\t starting writes\n");*/
239         reading=1;
240       }
241     }
242   }
243   exit(0);
244 }
245
246 -- 
247 Ian Jackson                  personal email: <ijackson@chiark.greenend.org.uk>
248 These opinions are my own.        http://www.chiark.greenend.org.uk/~ijackson/
249 PGP2 public key id 0x23f5addb, fingerprint 5906F687 BD03ACAD 0D8E602E FCF37657
250
251