diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2011-02-10 23:02:28 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-02-10 23:02:28 +0100 |
commit | f836f01cc3eb39e5e4c7186f50b456b57fae2010 (patch) | |
tree | 146e03c1f78155a9a5b4c3d8c7d1091653a7bdee | |
parent | 805aa9fec923109e90c87eda2f116ee2fa5fe962 (diff) | |
download | busybox-w32-f836f01cc3eb39e5e4c7186f50b456b57fae2010.tar.gz busybox-w32-f836f01cc3eb39e5e4c7186f50b456b57fae2010.tar.bz2 busybox-w32-f836f01cc3eb39e5e4c7186f50b456b57fae2010.zip |
wget: shrink progress meter code; strink wget and add debug logging
function old new delta
fgets_and_trim - 73 +73
retrieve_file_data 367 349 -18
bb_progress_update 723 699 -24
wget_main 2220 2190 -30
ftpcmd 133 87 -46
gethdr 200 153 -47
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 0/5 up/down: 73/-165) Total: -92 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | libbb/progress.c | 95 | ||||
-rw-r--r-- | networking/wget.c | 74 |
2 files changed, 105 insertions, 64 deletions
diff --git a/libbb/progress.c b/libbb/progress.c index ced04ac32..a490b8390 100644 --- a/libbb/progress.c +++ b/libbb/progress.c | |||
@@ -60,9 +60,16 @@ void FAST_FUNC bb_progress_init(bb_progress_t *p) | |||
60 | p->inited = 1; | 60 | p->inited = 1; |
61 | } | 61 | } |
62 | 62 | ||
63 | /* File already had beg_size bytes. | ||
64 | * Then we started downloading. | ||
65 | * We downloaded "transferred" bytes so far. | ||
66 | * Download is expected to stop when total size (beg_size + transferred) | ||
67 | * will be "totalsize" bytes. | ||
68 | * If totalsize == 0, then it is unknown. | ||
69 | */ | ||
63 | void FAST_FUNC bb_progress_update(bb_progress_t *p, | 70 | void FAST_FUNC bb_progress_update(bb_progress_t *p, |
64 | const char *curfile, | 71 | const char *curfile, |
65 | uoff_t beg_range, | 72 | uoff_t beg_size, |
66 | uoff_t transferred, | 73 | uoff_t transferred, |
67 | uoff_t totalsize) | 74 | uoff_t totalsize) |
68 | { | 75 | { |
@@ -72,32 +79,53 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, | |||
72 | int barlength; | 79 | int barlength; |
73 | int kiloscale; | 80 | int kiloscale; |
74 | 81 | ||
75 | /* totalsize == 0 if it is unknown */ | 82 | beg_and_transferred = beg_size + transferred; |
76 | |||
77 | beg_and_transferred = beg_range + transferred; | ||
78 | 83 | ||
79 | elapsed = monotonic_sec(); | 84 | elapsed = monotonic_sec(); |
80 | since_last_update = elapsed - p->lastupdate_sec; | 85 | since_last_update = elapsed - p->lastupdate_sec; |
81 | /* Do not update on every call | 86 | /* |
82 | * (we can be called on every network read!) */ | 87 | * Do not update on every call |
88 | * (we can be called on every network read!) | ||
89 | */ | ||
83 | if (since_last_update == 0 && beg_and_transferred < totalsize) | 90 | if (since_last_update == 0 && beg_and_transferred < totalsize) |
84 | return; | 91 | return; |
85 | 92 | ||
86 | /* Scale sizes down if they are close to overflowing. | ||
87 | * If off_t is only 32 bits, this allows calculations | ||
88 | * like (100 * transferred / totalsize) without risking overflow. | ||
89 | * Introduced error is < 0.1% | ||
90 | */ | ||
91 | kiloscale = 0; | 93 | kiloscale = 0; |
92 | if (totalsize >= (1 << 20)) { | 94 | /* |
93 | totalsize >>= 10; | 95 | * Scale sizes down if they are close to overflowing. |
94 | beg_range >>= 10; | 96 | * This allows calculations like (100 * transferred / totalsize) |
95 | transferred >>= 10; | 97 | * without risking overflow: we guarantee 10 highest bits to be 0. |
96 | beg_and_transferred >>= 10; | 98 | * Introduced error is less than 1 / 2^12 ~= 0.025% |
97 | kiloscale++; | 99 | */ |
100 | if (ULONG_MAX > 0xffffffff || sizeof(off_t) == 4 || sizeof(off_t) != 8) { | ||
101 | /* | ||
102 | * 64-bit CPU || small off_t: in either case, | ||
103 | * >> is cheap, single-word operation. | ||
104 | * ... || strange off_t: also use this code (it is safe, | ||
105 | * even if suboptimal), because 32/64 optimized one | ||
106 | * works only for 64-bit off_t. | ||
107 | */ | ||
108 | if (totalsize >= (1 << 22)) { | ||
109 | totalsize >>= 10; | ||
110 | beg_size >>= 10; | ||
111 | transferred >>= 10; | ||
112 | beg_and_transferred >>= 10; | ||
113 | kiloscale = 1; | ||
114 | } | ||
115 | } else { | ||
116 | /* 32-bit CPU and 64-bit off_t. | ||
117 | * Pick a shift (40 bits) which is easier to do on 32-bit CPU. | ||
118 | */ | ||
119 | if (totalsize >= (uoff_t)(1ULL << 54)) { | ||
120 | totalsize = (uint32_t)(totalsize >> 32) >> 8; | ||
121 | beg_size = (uint32_t)(beg_size >> 32) >> 8; | ||
122 | transferred = (uint32_t)(transferred >> 32) >> 8; | ||
123 | beg_and_transferred = (uint32_t)(beg_and_transferred >> 32) >> 8; | ||
124 | kiloscale = 4; | ||
125 | } | ||
98 | } | 126 | } |
99 | 127 | ||
100 | if (beg_and_transferred >= totalsize) | 128 | if (beg_and_transferred > totalsize) |
101 | beg_and_transferred = totalsize; | 129 | beg_and_transferred = totalsize; |
102 | 130 | ||
103 | ratio = 100 * beg_and_transferred / totalsize; | 131 | ratio = 100 * beg_and_transferred / totalsize; |
@@ -124,14 +152,14 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, | |||
124 | } | 152 | } |
125 | 153 | ||
126 | while (beg_and_transferred >= 100000) { | 154 | while (beg_and_transferred >= 100000) { |
127 | kiloscale++; | ||
128 | beg_and_transferred >>= 10; | 155 | beg_and_transferred >>= 10; |
156 | kiloscale++; | ||
129 | } | 157 | } |
130 | /* see http://en.wikipedia.org/wiki/Tera */ | 158 | /* see http://en.wikipedia.org/wiki/Tera */ |
131 | fprintf(stderr, "%6u%c ", (unsigned)beg_and_transferred, " kMGTPEZY"[kiloscale]); | 159 | fprintf(stderr, "%6u%c ", (unsigned)beg_and_transferred, " kMGTPEZY"[kiloscale]); |
132 | #define beg_and_transferred dont_use_beg_and_transferred_below() | 160 | #define beg_and_transferred dont_use_beg_and_transferred_below() |
133 | 161 | ||
134 | if (transferred > p->lastsize) { | 162 | if (transferred != p->lastsize) { |
135 | p->lastupdate_sec = elapsed; | 163 | p->lastupdate_sec = elapsed; |
136 | p->lastsize = transferred; | 164 | p->lastsize = transferred; |
137 | if (since_last_update >= STALLTIME) { | 165 | if (since_last_update >= STALLTIME) { |
@@ -141,20 +169,27 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, | |||
141 | } | 169 | } |
142 | since_last_update = 0; /* we are un-stalled now */ | 170 | since_last_update = 0; /* we are un-stalled now */ |
143 | } | 171 | } |
172 | |||
144 | elapsed -= p->start_sec; /* now it's "elapsed since start" */ | 173 | elapsed -= p->start_sec; /* now it's "elapsed since start" */ |
145 | 174 | ||
146 | if (since_last_update >= STALLTIME) { | 175 | if (since_last_update >= STALLTIME) { |
147 | fprintf(stderr, " - stalled -"); | 176 | fprintf(stderr, " - stalled -"); |
177 | } else if (!totalsize || !transferred || (int)elapsed <= 0) { | ||
178 | fprintf(stderr, "--:--:-- ETA"); | ||
148 | } else { | 179 | } else { |
149 | uoff_t to_download = totalsize - beg_range; | 180 | unsigned eta, secs, hours; |
150 | if (!totalsize || (int)elapsed <= 0 || transferred > to_download) { | 181 | |
151 | fprintf(stderr, "--:--:-- ETA"); | 182 | totalsize -= beg_size; /* now it's "total to upload" */ |
152 | } else { | 183 | |
153 | /* to_download / (transferred/elapsed) - elapsed: */ | 184 | /* Estimated remaining time = |
154 | unsigned eta = to_download * elapsed / transferred - elapsed; | 185 | * estimated_sec_to_dl_totalsize_bytes - elapsed_sec = |
155 | unsigned secs = eta % 3600; | 186 | * totalsize / average_bytes_sec_so_far - elapsed = |
156 | unsigned hours = eta / 3600; | 187 | * totalsize / (transferred/elapsed) - elapsed = |
157 | fprintf(stderr, "%02u:%02u:%02u ETA", hours, secs / 60, secs % 60); | 188 | * totalsize * elapsed / transferred - elapsed |
158 | } | 189 | */ |
190 | eta = totalsize * elapsed / transferred - elapsed; | ||
191 | secs = eta % 3600; | ||
192 | hours = eta / 3600; | ||
193 | fprintf(stderr, "%02u:%02u:%02u ETA", hours, secs / 60, secs % 60); | ||
159 | } | 194 | } |
160 | } | 195 | } |
diff --git a/networking/wget.c b/networking/wget.c index 931882fde..d81426e8d 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -10,6 +10,10 @@ | |||
10 | */ | 10 | */ |
11 | #include "libbb.h" | 11 | #include "libbb.h" |
12 | 12 | ||
13 | //#define log_io(...) bb_error_msg(__VA_ARGS__) | ||
14 | #define log_io(...) ((void)0) | ||
15 | |||
16 | |||
13 | struct host_info { | 17 | struct host_info { |
14 | // May be used if we ever will want to free() all xstrdup()s... | 18 | // May be used if we ever will want to free() all xstrdup()s... |
15 | /* char *allocated; */ | 19 | /* char *allocated; */ |
@@ -197,25 +201,39 @@ static FILE *open_socket(len_and_sockaddr *lsa) | |||
197 | return fp; | 201 | return fp; |
198 | } | 202 | } |
199 | 203 | ||
204 | /* Returns '\n' if it was seen, else '\0'. Trims at first '\r' or '\n' */ | ||
205 | static char fgets_and_trim(FILE *fp) | ||
206 | { | ||
207 | char c; | ||
208 | char *buf_ptr; | ||
209 | |||
210 | if (fgets(G.wget_buf, sizeof(G.wget_buf) - 1, fp) == NULL) | ||
211 | bb_perror_msg_and_die("error getting response"); | ||
212 | |||
213 | buf_ptr = strchrnul(G.wget_buf, '\n'); | ||
214 | c = *buf_ptr; | ||
215 | *buf_ptr = '\0'; | ||
216 | buf_ptr = strchrnul(G.wget_buf, '\r'); | ||
217 | *buf_ptr = '\0'; | ||
218 | |||
219 | log_io("< %s", G.wget_buf); | ||
220 | |||
221 | return c; | ||
222 | } | ||
223 | |||
200 | static int ftpcmd(const char *s1, const char *s2, FILE *fp) | 224 | static int ftpcmd(const char *s1, const char *s2, FILE *fp) |
201 | { | 225 | { |
202 | int result; | 226 | int result; |
203 | if (s1) { | 227 | if (s1) { |
204 | if (!s2) s2 = ""; | 228 | if (!s2) |
229 | s2 = ""; | ||
205 | fprintf(fp, "%s%s\r\n", s1, s2); | 230 | fprintf(fp, "%s%s\r\n", s1, s2); |
206 | fflush(fp); | 231 | fflush(fp); |
232 | log_io("> %s%s", s1, s2); | ||
207 | } | 233 | } |
208 | 234 | ||
209 | do { | 235 | do { |
210 | char *buf_ptr; | 236 | fgets_and_trim(fp); |
211 | |||
212 | if (fgets(G.wget_buf, sizeof(G.wget_buf)-2, fp) == NULL) { | ||
213 | bb_perror_msg_and_die("error getting response"); | ||
214 | } | ||
215 | buf_ptr = strstr(G.wget_buf, "\r\n"); | ||
216 | if (buf_ptr) { | ||
217 | *buf_ptr = '\0'; | ||
218 | } | ||
219 | } while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' '); | 237 | } while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' '); |
220 | 238 | ||
221 | G.wget_buf[3] = '\0'; | 239 | G.wget_buf[3] = '\0'; |
@@ -284,7 +302,7 @@ static void parse_url(char *src_url, struct host_info *h) | |||
284 | sp = h->host; | 302 | sp = h->host; |
285 | } | 303 | } |
286 | 304 | ||
287 | static char *gethdr(FILE *fp /*, int *istrunc*/) | 305 | static char *gethdr(FILE *fp) |
288 | { | 306 | { |
289 | char *s, *hdrval; | 307 | char *s, *hdrval; |
290 | int c; | 308 | int c; |
@@ -292,19 +310,16 @@ static char *gethdr(FILE *fp /*, int *istrunc*/) | |||
292 | /* *istrunc = 0; */ | 310 | /* *istrunc = 0; */ |
293 | 311 | ||
294 | /* retrieve header line */ | 312 | /* retrieve header line */ |
295 | if (fgets(G.wget_buf, sizeof(G.wget_buf), fp) == NULL) | 313 | c = fgets_and_trim(fp); |
296 | return NULL; | ||
297 | 314 | ||
298 | /* see if we are at the end of the headers */ | 315 | /* end of the headers? */ |
299 | for (s = G.wget_buf; *s == '\r'; ++s) | 316 | if (G.wget_buf[0] == '\0') |
300 | continue; | ||
301 | if (*s == '\n') | ||
302 | return NULL; | 317 | return NULL; |
303 | 318 | ||
304 | /* convert the header name to lower case */ | 319 | /* convert the header name to lower case */ |
305 | for (s = G.wget_buf; isalnum(*s) || *s == '-' || *s == '.'; ++s) { | 320 | for (s = G.wget_buf; isalnum(*s) || *s == '-' || *s == '.'; ++s) { |
306 | /* tolower for "A-Z", no-op for "0-9a-z-." */ | 321 | /* tolower for "A-Z", no-op for "0-9a-z-." */ |
307 | *s = (*s | 0x20); | 322 | *s |= 0x20; |
308 | } | 323 | } |
309 | 324 | ||
310 | /* verify we are at the end of the header name */ | 325 | /* verify we are at the end of the header name */ |
@@ -315,20 +330,12 @@ static char *gethdr(FILE *fp /*, int *istrunc*/) | |||
315 | *s++ = '\0'; | 330 | *s++ = '\0'; |
316 | hdrval = skip_whitespace(s); | 331 | hdrval = skip_whitespace(s); |
317 | 332 | ||
318 | /* locate the end of header */ | 333 | if (c != '\n') { |
319 | while (*s && *s != '\r' && *s != '\n') | 334 | /* Rats! The buffer isn't big enough to hold the entire header value */ |
320 | ++s; | 335 | while (c = getc(fp), c != EOF && c != '\n') |
321 | 336 | continue; | |
322 | /* end of header found */ | ||
323 | if (*s) { | ||
324 | *s = '\0'; | ||
325 | return hdrval; | ||
326 | } | 337 | } |
327 | 338 | ||
328 | /* Rats! The buffer isn't big enough to hold the entire header value */ | ||
329 | while (c = getc(fp), c != EOF && c != '\n') | ||
330 | continue; | ||
331 | /* *istrunc = 1; */ | ||
332 | return hdrval; | 339 | return hdrval; |
333 | } | 340 | } |
334 | 341 | ||
@@ -520,9 +527,9 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd) | |||
520 | if (!G.chunked) | 527 | if (!G.chunked) |
521 | break; | 528 | break; |
522 | 529 | ||
523 | fgets(G.wget_buf, sizeof(G.wget_buf), dfp); /* This is a newline */ | 530 | fgets_and_trim(dfp); /* This is a newline */ |
524 | get_clen: | 531 | get_clen: |
525 | fgets(G.wget_buf, sizeof(G.wget_buf), dfp); | 532 | fgets_and_trim(dfp); |
526 | G.content_len = STRTOOFF(G.wget_buf, NULL, 16); | 533 | G.content_len = STRTOOFF(G.wget_buf, NULL, 16); |
527 | /* FIXME: error check? */ | 534 | /* FIXME: error check? */ |
528 | if (G.content_len == 0) | 535 | if (G.content_len == 0) |
@@ -757,8 +764,7 @@ int wget_main(int argc UNUSED_PARAM, char **argv) | |||
757 | * Retrieve HTTP response line and check for "200" status code. | 764 | * Retrieve HTTP response line and check for "200" status code. |
758 | */ | 765 | */ |
759 | read_response: | 766 | read_response: |
760 | if (fgets(G.wget_buf, sizeof(G.wget_buf), sfp) == NULL) | 767 | fgets_and_trim(sfp); |
761 | bb_error_msg_and_die("no response from server"); | ||
762 | 768 | ||
763 | str = G.wget_buf; | 769 | str = G.wget_buf; |
764 | str = skip_non_whitespace(str); | 770 | str = skip_non_whitespace(str); |