When executed with a single argument 'DOWNLOADER', grabber.py parses download requests on stdin, and reports the results to stdout.
Conflicts: urlgrabber/grabber.py --- urlgrabber/grabber.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 63 insertions(+), 1 deletions(-) diff --git a/urlgrabber/grabber.py b/urlgrabber/grabber.py index e447435..a8b118c 100644 --- a/urlgrabber/grabber.py +++ b/urlgrabber/grabber.py @@ -455,7 +455,7 @@ import pycurl from ftplib import parse150 from StringIO import StringIO from httplib import HTTPException -import socket +import socket, select from byterange import range_tuple_normalize, range_tuple_to_header, RangeError try: @@ -1986,6 +1986,65 @@ def _loads(s): ##################################################################### +# External downloader process +##################################################################### + +class _ProxyProgress: + def start(*d1, **d2): pass + def update(self, _amount_read): + os.write(1, '%d %d\n' % (self._id, _amount_read)) + +def _readlines(fd): + buf = os.read(fd, 4096) + if not buf: return None + # whole lines only, no buffering + while buf[-1] != '\n': + buf += os.read(fd, 4096) + return buf[:-1].split('\n') + +def download_process(): + ''' Download process + - watch stdin for new requests, parse & issue em. + - use ProxyProgress to send _amount_read during dl. + - abort on EOF. + ''' + sys.stderr.close() + dl = _DirectDownloader() + cnt = tout = 0 + while True: + fdset = dl.multi.fdset() + fdset[0].append(0) # stdin + fdset = select.select(*(fdset + (tout,))) + if 0 in fdset[0]: + lines = _readlines(0) + if not lines: break + for line in lines: + # start new download + cnt += 1 + opts = URLGrabberOptions() + opts._id = cnt + opts.progress_obj = _ProxyProgress() + opts.progress_obj._id = cnt + for k in line.split(' '): + k, v = k.split('=', 1) + setattr(opts, k, _loads(v)) + dl.start(opts) + + # XXX: likely a CurlMulti() bug + # fdset() is empty shortly after starting new request. + # Do some polling to work this around. + tout = 10e-3 + + # perform requests + for opts, ug_err, _amount_read in dl.perform(): + ug_err = ug_err and '%d %s' % ug_err.args or 'OK' + os.write(1, '%d %d %s\n' % (opts._id, _amount_read, ug_err)) + tout = min(tout * 1.1, 5) + dl.abort() + sys.exit(0) + + +##################################################################### # High level async API ##################################################################### @@ -2206,6 +2265,9 @@ def _test_file_object_readlines(wrapper, fo_output): fo_output.write(string.join(li, '')) if __name__ == '__main__': + if sys.argv[1:] == ['DOWNLOADER']: + download_process() + _main_test() _retry_test() _file_object_test('test') -- 1.7.4.4 _______________________________________________ Yum-devel mailing list Yum-devel@lists.baseurl.org http://lists.baseurl.org/mailman/listinfo/yum-devel