From eb72da611ddab59f6413e4358740bdb2a2bed0ad Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 25 May 2015 21:01:06 +0530 Subject: [PATCH] ... --- src/calibre/srv/http_response.py | 3 +++ src/calibre/srv/sendfile.py | 5 +++-- src/calibre/srv/tests/http.py | 19 ++++++++++++------- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/calibre/srv/http_response.py b/src/calibre/srv/http_response.py index 0e38ea8a91..afbd11fe2a 100644 --- a/src/calibre/srv/http_response.py +++ b/src/calibre/srv/http_response.py @@ -24,6 +24,7 @@ from calibre.srv.errors import HTTP404 from calibre.srv.http_request import HTTPRequest, read_headers from calibre.srv.sendfile import file_metadata, sendfile_to_socket_async, CannotSendfile, SendfileInterrupted from calibre.srv.utils import MultiDict, start_cork, stop_cork, http_date, HTTP1, HTTP11, socket_errors_socket_closed +from calibre.utils.monotonic import monotonic Range = namedtuple('Range', 'start stop size') MULTIPART_SEPARATOR = uuid.uuid4().hex.decode('ascii') @@ -274,6 +275,8 @@ class HTTPConnection(HTTPRequest): self.ready = self.use_sendfile = False return False raise + finally: + self.last_activity = monotonic() if sent == 0: # Something bad happened, was the file modified on disk by # another process? diff --git a/src/calibre/srv/sendfile.py b/src/calibre/srv/sendfile.py index a740008332..ade243e50b 100644 --- a/src/calibre/srv/sendfile.py +++ b/src/calibre/srv/sendfile.py @@ -80,9 +80,10 @@ if isosx: err = ctypes.get_errno() if err in (errno.EBADF, errno.ENOTSUP, errno.ENOTSOCK, errno.EOPNOTSUPP): raise CannotSendfile() - if err in (errno.EINTR, errno.EAGAIN): + if err == errno.EINTR: raise SendfileInterrupted() - raise IOError((err, os.strerror(err))) + if err != errno.EAGAIN: + raise IOError((err, os.strerror(err))) return num_bytes.value elif islinux: diff --git a/src/calibre/srv/tests/http.py b/src/calibre/srv/tests/http.py index f34e6b7176..02bc2e96a8 100644 --- a/src/calibre/srv/tests/http.py +++ b/src/calibre/srv/tests/http.py @@ -12,6 +12,7 @@ from tempfile import NamedTemporaryFile from calibre import guess_type from calibre.srv.tests.base import BaseTest, TestServer +from calibre.utils.monotonic import monotonic class TestHTTP(BaseTest): @@ -242,8 +243,8 @@ class TestHTTP(BaseTest): from calibre.srv.http_response import parse_multipart_byterange def handler(conn): return conn.generate_static_output('test', lambda : ''.join(conn.path)) - with TestServer(handler, timeout=0.1, compress_min_size=0) as server, \ - NamedTemporaryFile(suffix='test.epub') as f, open(P('localization/locales.zip'), 'rb') as lf: + with NamedTemporaryFile(suffix='test.epub') as f, open(P('localization/locales.zip'), 'rb') as lf, \ + TestServer(handler, timeout=0.2, compress_min_size=0) as server: fdata = string.ascii_letters * 100 f.write(fdata), f.seek(0) @@ -280,20 +281,21 @@ class TestHTTP(BaseTest): conn.request('GET', '/test', headers={'Range':'bytes=2-25'}) r = conn.getresponse() + self.ae(r.status, httplib.PARTIAL_CONTENT) self.ae(type('')(r.getheader('Accept-Ranges')), 'bytes') self.ae(type('')(r.getheader('Content-Range')), 'bytes 2-25/%d' % len(fdata)) self.ae(int(r.getheader('Content-Length')), 24) - self.ae(r.status, httplib.PARTIAL_CONTENT), self.ae(r.read(), fdata[2:26]) + self.ae(r.read(), fdata[2:26]) conn.request('GET', '/test', headers={'Range':'bytes=100000-'}) r = conn.getresponse() - self.ae(type('')(r.getheader('Content-Range')), 'bytes */%d' % len(fdata)) self.ae(r.status, httplib.REQUESTED_RANGE_NOT_SATISFIABLE) + self.ae(type('')(r.getheader('Content-Range')), 'bytes */%d' % len(fdata)) conn.request('GET', '/test', headers={'Range':'bytes=25-50', 'If-Range':etag}) r = conn.getresponse() - self.ae(int(r.getheader('Content-Length')), 26) self.ae(r.status, httplib.PARTIAL_CONTENT), self.ae(r.read(), fdata[25:51]) + self.ae(int(r.getheader('Content-Length')), 26) conn.request('GET', '/test', headers={'Range':'bytes=0-1000000'}) r = conn.getresponse() @@ -301,12 +303,13 @@ class TestHTTP(BaseTest): conn.request('GET', '/test', headers={'Range':'bytes=25-50', 'If-Range':'"nomatch"'}) r = conn.getresponse() + self.ae(r.status, httplib.OK), self.ae(r.read(), fdata) self.assertFalse(r.getheader('Content-Range')) self.ae(int(r.getheader('Content-Length')), len(fdata)) - self.ae(r.status, httplib.OK), self.ae(r.read(), fdata) conn.request('GET', '/test', headers={'Range':'bytes=0-25,26-50'}) r = conn.getresponse() + self.ae(r.status, httplib.PARTIAL_CONTENT) clen = int(r.getheader('Content-Length')) data = r.read() self.ae(clen, len(data)) @@ -314,16 +317,18 @@ class TestHTTP(BaseTest): self.ae(parse_multipart_byterange(buf, r.getheader('Content-Type')), [(0, fdata[:26]), (26, fdata[26:51])]) # Test sending of larger file + start_time = monotonic() lf.seek(0) data = lf.read() server.change_handler(lambda conn: lf) conn = server.connect() conn.request('GET', '/test') r = conn.getresponse() + self.ae(r.status, httplib.OK) rdata = r.read() self.ae(len(data), len(rdata)) self.ae(hashlib.sha1(data).hexdigest(), hashlib.sha1(rdata).hexdigest()) self.ae(data, rdata) + self.assertLess(monotonic() - start_time, 5, 'Large file transfer took too long') - # Now try it without sendfile # }}}