When executed with a single argument 'DOWNLOADER', grabber.py
parses download requests on stdin, and reports the results to stdout.
---
 urlgrabber/grabber.py |   57 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 56 insertions(+), 1 deletions(-)

diff --git a/urlgrabber/grabber.py b/urlgrabber/grabber.py
index b64c943..6d75c31 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:
@@ -1899,6 +1899,58 @@ class _DirectDownloader:
             fo._do_close_fo()
             os.unlink(fo.opts.filename)
 
+class _ProxyProgress:
+    def start(*d1, **d2): pass
+    def update(self, _amount_read):
+        os.write(1, '%d %d\n' % (self._id, _amount_read))
+
+import simplejson
+
+def download_process():
+    ''' Download process
+        - watch stdin for new requests, parse & issue em.
+        - use ProxyProgress to send _amount_read during dl.
+        - abort on EOF.
+    '''
+    dl = _DirectDownloader()
+    cnt = tout = 0
+    while True:
+        fdset = dl.multi.fdset()
+        fdset[0].append(0)
+        if 0 in select.select(*(fdset + (tout,)))[0]:
+            buf = os.read(0, 4096)
+            if not buf: break # EOF
+            while buf:
+                try: line, buf = buf.split('\n', 1)
+                except ValueError:
+                    buf += os.read(0, 4096)
+                    continue
+                # 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)
+                    v = urllib.unquote(v)
+                    v = simplejson.loads(v)
+                    setattr(opts, k, 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
@@ -2122,6 +2174,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

Reply via email to