Ejemplo n.º 1
0
    def restart(self, forced=False):
        from calibre.utils.rapydscript import compile_srv, CompileFailure
        self.clean_kill()
        if forced:
            self.retry_count += 1
        else:
            self.retry_count = 0
        try:
            compile_srv()
        except EnvironmentError as e:
            # Happens if the editor deletes and replaces a file being edited
            if e.errno != errno.ENOENT or not getattr(e, 'filename', False):
                raise
            st = monotonic()
            while not os.path.exists(e.filename) and monotonic() - st < 3:
                time.sleep(0.01)
            compile_srv()
        except CompileFailure as e:
            self.log.error(e.message)
            time.sleep(0.1 * self.retry_count)
            if self.retry_count < MAX_RETRIES and self.wakeup is not None:
                self.wakeup()  # Force a restart
            return

        self.retry_count = 0
        self.p = subprocess.Popen(self.cmd, creationflags=getattr(subprocess, 'CREATE_NEW_PROCESS_GROUP', 0))
        self.wait_for_listen()
        self.server.notify_reload()
Ejemplo n.º 2
0
 def read_upgrade_response(self):
     from calibre.srv.http_request import read_headers
     st = monotonic()
     buf, idx = b'', -1
     while idx == -1:
         data = self.socket.recv(1024)
         if not data:
             raise ValueError('Server did not respond with a valid HTTP upgrade response')
         buf += data
         if len(buf) > 4096:
             raise ValueError('Server responded with too much data to HTTP upgrade request')
         if monotonic() - st > self.timeout:
             raise ValueError('Timed out while waiting for server response to HTTP upgrade')
         idx = buf.find(b'\r\n\r\n')
     response, rest = buf[:idx+4], buf[idx+4:]
     if rest:
         self.read_buf.append(rest)
     lines = (x + b'\r\n' for x in response.split(b'\r\n')[:-1])
     rl = next(lines)
     if rl != b'HTTP/1.1 101 Switching Protocols\r\n':
         raise ValueError('Server did not respond with correct switching protocols line')
     headers = read_headers(partial(next, lines))
     key = standard_b64encode(sha1(self.key + GUID_STR).digest())
     if headers.get('Sec-WebSocket-Accept') != key:
         raise ValueError('Server did not respond with correct key in Sec-WebSocket-Accept')
Ejemplo n.º 3
0
 def wait_for_listen(self):
     st = monotonic()
     while monotonic() - st < 5:
         try:
             return socket.create_connection(('localhost', self.port), 5).close()
         except socket.error:
             time.sleep(0.01)
     self.log.error('Restarted server did not start listening on:', self.port)
Ejemplo n.º 4
0
 def load_header_footer_images(self):
     from calibre.utils.monotonic import monotonic
     evaljs = self.view.page().mainFrame().evaluateJavaScript
     st = monotonic()
     while not evaljs('paged_display.header_footer_images_loaded()'):
         self.loop.processEvents(self.loop.ExcludeUserInputEvents)
         if monotonic() - st > 5:
             self.log.warn('Header and footer images have not loaded in 5 seconds, ignoring')
             break
Ejemplo n.º 5
0
def retry_lock_tdir(path, timeout=30, sleep=0.1):
    st = monotonic()
    while True:
        try:
            return lock_tdir(path)
        except Exception:
            if monotonic() - st > timeout:
                raise
            time.sleep(sleep)
Ejemplo n.º 6
0
def retry_for_a_time(timeout, sleep_time, func, error_retry, *args):
    limit = monotonic() + timeout
    while True:
        try:
            return func(*args)
        except EnvironmentError as err:
            if not error_retry(err) or monotonic() > limit:
                raise
        time.sleep(sleep_time)
Ejemplo n.º 7
0
 def wait_for_shutdown(self, wait_till):
     for job in itervalues(self.jobs):
         delta = wait_till - monotonic()
         if delta > 0:
             job.join(delta)
     if self.event_loop is not None:
         delta = wait_till - monotonic()
         if delta > 0:
             self.event_loop.join(delta)
Ejemplo n.º 8
0
 def handle_modified(self, modified):
     if modified:
         if monotonic() - self.last_restart_time > self.BOUNCE_INTERVAL:
             modified = {os.path.relpath(x, self.base) if x.startswith(self.base) else x for x in modified if x}
             changed = os.pathsep.join(sorted(modified))
             self.log('')
             self.log.warn('Restarting server because of changed files:', changed)
             self.log('')
             self.worker.restart()
             self.last_restart_time = monotonic()
Ejemplo n.º 9
0
 def test_monotonic(self):
     'Test the monotonic() clock'
     a = monotonic()
     b = monotonic()
     self.assertGreaterEqual(b, a)
     a = monotonic()
     time.sleep(0.1)
     b = monotonic()
     self.assertGreaterEqual(b, a)
     self.assertGreaterEqual(b - a, 0.09)
     self.assertLessEqual(b - a, 0.2)
Ejemplo n.º 10
0
def query(br, url, key, dump_raw=None, limit=1, parser=parse_html, timeout=60):
    delta = monotonic() - last_visited[key]
    if delta < limit and delta > 0:
        time.sleep(delta)
    try:
        raw = br.open_novisit(url, timeout=timeout).read()
    finally:
        last_visited[key] = monotonic()
    if dump_raw is not None:
        with open(dump_raw, 'wb') as f:
            f.write(raw)
    return parser(raw)
Ejemplo n.º 11
0
 def wait_for_listen(self):
     st = monotonic()
     while monotonic() - st < 5:
         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         s.settimeout(5)
         try:
             if self.uses_ssl:
                 s = ssl.wrap_socket(s)
             s.connect(('localhost', self.port))
             s.close()
             return
         except socket.error:
             time.sleep(0.01)
     self.log.error('Restarted server did not start listening on:', self.port)
Ejemplo n.º 12
0
def handle_gesture(ev, view):
    tap = ev.gesture(Qt.TapGesture)
    if tap and tap.state() == Qt.GestureFinished:
        p, view.last_tap_at = view.last_tap_at, monotonic()
        interval = QApplication.instance().doubleClickInterval() / 1000
        double_click = monotonic() - p < interval
        send_click(view, tap.position(), double_click=double_click)
        ev.accept(Qt.TapGesture)
        return True
    th = ev.gesture(Qt.TapAndHoldGesture)
    if th and th.state() in (Qt.GestureStarted, Qt.GestureUpdated, Qt.GestureFinished):
        send_click(view, th.position(), button=Qt.RightButton)
        ev.accept(Qt.TapAndHoldGesture)
        return True
    return True
Ejemplo n.º 13
0
 def test_jobs_manager(self):
     'Test the jobs manager'
     from calibre.srv.jobs import JobsManager
     O = namedtuple('O', 'max_jobs max_job_time')
     class FakeLog(list):
         def error(self, *args):
             self.append(' '.join(args))
     jm = JobsManager(O(1, 5), FakeLog())
     job_id = jm.start_job('simple test', 'calibre.srv.jobs', 'sleep_test', args=(1.0,))
     job_id2 = jm.start_job('t2', 'calibre.srv.jobs', 'sleep_test', args=(3,))
     jid = jm.start_job('err test', 'calibre.srv.jobs', 'error_test')
     status = jm.job_status(job_id)[0]
     s = ('waiting', 'running')
     self.assertIn(status, s)
     status2 = jm.job_status(job_id2)[0]
     self.assertEqual(status2, 'waiting')
     while jm.job_status(job_id)[0] in s:
         time.sleep(0.01)
     status, result, tb, was_aborted = jm.job_status(job_id)
     self.assertEqual(status, 'finished')
     self.assertFalse(was_aborted)
     self.assertFalse(tb)
     self.assertEqual(result, 1.0)
     status2 = jm.job_status(job_id2)[0]
     time.sleep(0.01)
     self.assertEqual(status2, 'running')
     jm.abort_job(job_id2)
     self.assertTrue(jm.wait_for_running_job(job_id2))
     status, result, tb, was_aborted = jm.job_status(job_id2)
     self.assertTrue(was_aborted)
     self.assertTrue(jm.wait_for_running_job(jid))
     status, result, tb, was_aborted = jm.job_status(jid)
     self.assertTrue(tb), self.assertIn('a testing error', tb)
     jm.start_job('simple test', 'calibre.srv.jobs', 'sleep_test', args=(1.0,))
     jm.shutdown(), jm.wait_for_shutdown(monotonic() + 1)
Ejemplo n.º 14
0
 def write(self, buf, end=None):
     pos = buf.tell()
     if end is None:
         buf.seek(0, os.SEEK_END)
         end = buf.tell()
         buf.seek(pos)
     limit = end - pos
     if limit == 0:
         return True
     if self.use_sendfile and not isinstance(buf, (BytesIO, ReadOnlyFileBuffer)):
         try:
             sent = sendfile_to_socket_async(buf, pos, limit, self.socket)
         except CannotSendfile:
             self.use_sendfile = False
             return False
         except SendfileInterrupted:
             return False
         except IOError as e:
             if e.errno in socket_errors_socket_closed:
                 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?
             self.use_sendfile = self.ready = False
             raise IOError('sendfile() failed to write any bytes to the socket')
     else:
         sent = self.send(buf.read(min(limit, self.send_bufsize)))
     buf.seek(pos + sent)
     return buf.tell() == end
Ejemplo n.º 15
0
 def __init__(self, socket, opts, ssl_context, tdir, addr, pool, log, access_log, wakeup):
     self.opts, self.pool, self.log, self.wakeup, self.access_log = opts, pool, log, wakeup, access_log
     try:
         self.remote_addr = addr[0]
         self.remote_port = addr[1]
     except Exception:
         # In case addr is None, which can occassionally happen
         self.remote_addr = self.remote_port = None
     self.is_local_connection = self.remote_addr in ('127.0.0.1', '::1')
     self.orig_send_bufsize = self.send_bufsize = 4096
     self.tdir = tdir
     self.wait_for = READ
     self.response_started = False
     self.read_buffer = ReadBuffer()
     self.handle_event = None
     self.ssl_context = ssl_context
     self.ssl_handshake_done = False
     self.ssl_terminated = False
     if self.ssl_context is not None:
         self.ready = False
         self.socket = self.ssl_context.wrap_socket(socket, server_side=True, do_handshake_on_connect=False)
         self.set_state(RDWR, self.do_ssl_handshake)
     else:
         self.socket = socket
         self.connection_ready()
     self.last_activity = monotonic()
     self.ready = True
Ejemplo n.º 16
0
 def recv(self, amt):
     # If there is data in the read buffer we have to return only that,
     # since we dont know if the socket has signalled it is ready for
     # reading
     if self.read_buffer.has_data:
         return self.read_buffer.read(amt)
     # read buffer is empty, so read directly from socket
     try:
         data = self.socket.recv(amt)
         self.last_activity = monotonic()
         if not data:
             # a closed connection is indicated by signaling
             # a read condition, and having recv() return 0.
             self.ready = False
             return b''
         return data
     except ssl.SSLWantReadError:
         return b''
     except socket.error as e:
         if e.errno in socket_errors_nonblocking or e.errno in socket_errors_eintr:
             return b''
         if e.errno in socket_errors_socket_closed:
             self.ready = False
             return b''
         raise
Ejemplo n.º 17
0
 def __init__(self, tp):
     self.creation_time = self.last_update_time = self.time_of_last_move = monotonic()
     self.start_screen_position = self.current_screen_position = self.previous_screen_position = QPointF(tp.screenPos())
     self.time_since_last_update = -1
     self.total_movement = 0
     self.start_position = self.current_position = tp.pos()
     self.extra_data = None
Ejemplo n.º 18
0
 def start_gui(self, db):
     from calibre.gui2.ui import Main
     self.timed_print('Constructing main UI...')
     main = self.main = Main(self.opts, gui_debug=self.gui_debug)
     if self.splash_screen is not None:
         self.splash_screen.show_message(_('Initializing user interface...'))
     try:
         with gprefs:  # Only write gui.json after initialization is complete
             main.initialize(self.library_path, db, self.listener, self.actions)
     finally:
         self.timed_print('main UI initialized...')
         if self.splash_screen is not None:
             self.timed_print('Hiding splash screen')
             self.splash_screen.finish(main)
             self.timed_print('splash screen hidden')
         self.splash_screen = None
     self.timed_print('Started up in %.2f seconds'%(monotonic() - self.startup_time), 'with', len(db.data), 'books')
     add_filesystem_book = partial(main.iactions['Add Books'].add_filesystem_book, allow_device=False)
     main.set_exception_handler()
     if len(self.args) > 1:
         files = [os.path.abspath(p) for p in self.args[1:] if not
                 os.path.isdir(p)]
         if len(files) < len(sys.argv[1:]):
             prints('Ignoring directories passed as command line arguments')
         if files:
             add_filesystem_book(files)
     for event in self.app.file_event_hook.events:
         add_filesystem_book(event)
     self.app.file_event_hook = add_filesystem_book
Ejemplo n.º 19
0
def is_nonce_stale(nonce, max_age_seconds=MAX_AGE_SECONDS):
    try:
        timestamp = struct.unpack(b'!dH', binascii.unhexlify(as_bytestring(nonce.partition(':')[0])))[0]
        return timestamp + max_age_seconds < monotonic()
    except Exception:
        pass
    return True
Ejemplo n.º 20
0
def conversion_status(ctx, rd, job_id):
    with cache_lock:
        job_status = conversion_jobs.get(job_id)
        if job_status is None:
            raise HTTPNotFound('No job with id: {}'.format(job_id))
        job_status.last_check_at = monotonic()
        if job_status.running:
            percent, msg = job_status.current_status
            if rd.query.get('abort_job'):
                ctx.abort_job(job_id)
            return {'running': True, 'percent': percent, 'msg': msg}

        del conversion_jobs[job_id]

    try:
        ans = {'running': False, 'ok': job_status.ok, 'was_aborted':
               job_status.was_aborted, 'traceback': job_status.traceback,
               'log': job_status.log}
        if job_status.ok:
            db, library_id = get_library_data(ctx, rd)[:2]
            if library_id != job_status.library_id:
                raise HTTPNotFound('job library_id does not match')
            fmt = job_status.output_path.rpartition('.')[-1]
            try:
                db.add_format(job_status.book_id, fmt, job_status.output_path)
            except NoSuchBook:
                raise HTTPNotFound(
                    'book_id {} not found in library'.format(job_status.book_id))
            formats_added({job_status.book_id: (fmt,)})
            ans['size'] = os.path.getsize(job_status.output_path)
            ans['fmt'] = fmt
        return ans
    finally:
        job_status.cleanup()
Ejemplo n.º 21
0
 def _prune_loaded_dbs(self):
     now = monotonic()
     for library_id in tuple(self.loaded_dbs):
         if library_id != self.gui_library_id and now - self.last_used_times[
             library_id] > EXPIRED_AGE:
             db = self.loaded_dbs.pop(library_id)
             db.close()
             db.break_cycles()
Ejemplo n.º 22
0
    def render_next(self):
        item = unicode_type(self.render_queue.pop(0))

        self.logger.debug('Processing %s...' % item)
        self.current_item = item
        load_html(item, self.view)
        self.last_load_progress_at = monotonic()
        self.hang_check_timer.start()
Ejemplo n.º 23
0
 def handle_tap(self, tp):
     self.scroller.stop()
     last_tap_at, self.last_tap_at = self.last_tap_at, monotonic()
     if self.close_open_menu():
         return
     interval = QApplication.instance().doubleClickInterval() / 1000
     double_tap = self.last_tap_at - last_tap_at < interval
     send_click(self.parent(), tp.start_position, double_click=double_tap)
Ejemplo n.º 24
0
def expire_old_jobs():
    now = monotonic()
    with cache_lock:
        remove = [job_id for job_id, job_status in conversion_jobs.iteritems(
        ) if now - job_status.last_check_at >= 360]
        for job_id in remove:
            job_status = conversion_jobs.pop(job_id)
            job_status.cleanup()
Ejemplo n.º 25
0
def timing():
    import sys
    from calibre.ebooks.chardet import xml_to_unicode
    from calibre.utils.monotonic import monotonic
    from html5lib import parse as vanilla
    filename = sys.argv[-1]
    with lopen(filename, 'rb') as f:
        raw = f.read()
    raw = xml_to_unicode(raw)[0]

    for name, f in (('calibre', partial(parse, line_numbers=False)), ('html5lib', vanilla), ('calibre-old', html5_parse)):
        timings = []
        for i in xrange(10):
            st = monotonic()
            f(raw)
            timings.append(monotonic() - st)
        avg = sum(timings)/len(timings)
        print ('Average time for %s: %.2g' % (name, avg))
Ejemplo n.º 26
0
    def test_jobs_manager(self):
        'Test the jobs manager'
        from calibre.srv.jobs import JobsManager
        O = namedtuple('O', 'max_jobs max_job_time')

        class FakeLog(list):

            def error(self, *args):
                self.append(' '.join(args))
        s = ('waiting', 'running')
        jm = JobsManager(O(1, 5), FakeLog())

        def job_status(jid):
            return jm.job_status(jid)[0]

        # Start jobs
        job_id1 = jm.start_job('simple test', 'calibre.srv.jobs', 'sleep_test', args=(1.0,))
        job_id2 = jm.start_job('t2', 'calibre.srv.jobs', 'sleep_test', args=(3,))
        job_id3 = jm.start_job('err test', 'calibre.srv.jobs', 'error_test')

        # Job 1
        job_id = job_id1
        status = jm.job_status(job_id)[0]
        self.assertIn(status, s)
        for jid in (job_id2, job_id3):
            self.assertEqual(job_status(jid), 'waiting')
        while job_status(job_id) in s:
            time.sleep(0.01)
        status, result, tb, was_aborted = jm.job_status(job_id)
        self.assertEqual(status, 'finished')
        self.assertFalse(was_aborted)
        self.assertFalse(tb)
        self.assertEqual(result, 1.0)

        # Job 2
        job_id = job_id2
        while job_status(job_id) == 'waiting':
            time.sleep(0.01)
        self.assertEqual('running', job_status(job_id))
        jm.abort_job(job_id)
        self.assertIn(jm.wait_for_running_job(job_id), (True, None))
        status, result, tb, was_aborted = jm.job_status(job_id)
        self.assertEqual('finished', status)
        self.assertTrue(was_aborted)

        # Job 3
        job_id = job_id3
        while job_status(job_id) == 'waiting':
            time.sleep(0.01)
        self.assertIn(jm.wait_for_running_job(job_id), (True, None))
        status, result, tb, was_aborted = jm.job_status(job_id)
        self.assertEqual(status, 'finished')
        self.assertFalse(was_aborted)
        self.assertTrue(tb)
        self.assertIn('a testing error', tb)
        jm.start_job('simple test', 'calibre.srv.jobs', 'sleep_test', args=(1.0,))
        jm.shutdown(), jm.wait_for_shutdown(monotonic() + 1)
Ejemplo n.º 27
0
 def stopTest(self, test):
     orig = self.stream.writeln
     self.stream.writeln = self.stream.write
     super(TestResult, self).stopTest(test)
     elapsed = monotonic()
     elapsed -= self.start_time.get(test, elapsed)
     self.times[test] = elapsed
     self.stream.writeln = orig
     self.stream.writeln(' [%.1g s]' % elapsed)
Ejemplo n.º 28
0
 def prune_finished_jobs(self):
     with self.lock:
         remove = []
         now = monotonic()
         for job_id, job in iteritems(self.finished_jobs):
             if now - job.end_time > 3600:
                 remove.append(job_id)
         for job_id in remove:
             del self.finished_jobs[job_id]
Ejemplo n.º 29
0
 def is_banned(self, key):
     with self.lock:
         x = self.items.get(key)
     if x is None:
         return False
     previous_fail, fail_count = x
     if fail_count < self.max_failures_before_ban:
         return False
     return monotonic() - previous_fail < self.interval
Ejemplo n.º 30
0
 def __init__(self, opts, args, actions, listener, app, gui_debug=None):
     self.startup_time = monotonic()
     self.timed_print('Starting up...')
     self.opts, self.args, self.listener, self.app = opts, args, listener, app
     self.gui_debug = gui_debug
     self.actions = actions
     self.main = None
     QObject.__init__(self)
     self.splash_screen = None
     self.timer = QTimer.singleShot(1, self.initialize)
Ejemplo n.º 31
0
 def do_one(self, book_id, fmt):
     db = self.gui.current_db
     path = db.format(book_id, fmt, index_is_id=True, as_path=True)
     title = db.title(book_id, index_is_id=True) + ' [%s]'%fmt
     data = {'path': path, 'title': title}
     self.gui.job_manager.launch_gui_app('toc-dialog', kwargs=data)
     job = data.copy()
     job.update({'book_id': book_id, 'fmt': fmt, 'library_id': db.new_api.library_id, 'started': False, 'start_time': monotonic()})
     self.jobs.append(job)
     self.check_for_completions()
Ejemplo n.º 32
0
 def hang_check(self):
     if monotonic() - self.last_load_progress_at > 60:
         self.log.warn('Timed out waiting for %s to render' %
                       self.current_item)
         self.ignore_failure = self.current_item
         self.view.stop()
Ejemplo n.º 33
0
 def force_restart(self):
     self.worker.restart(forced=True)
     self.last_restart_time = monotonic()
Ejemplo n.º 34
0
    def test_jobs_manager(self):
        'Test the jobs manager'
        from calibre.srv.jobs import JobsManager
        O = namedtuple('O', 'max_jobs max_job_time')

        class FakeLog(list):
            def error(self, *args):
                self.append(' '.join(args))

        s = ('waiting', 'running')
        jm = JobsManager(O(1, 5), FakeLog())

        def job_status(jid):
            return jm.job_status(jid)[0]

        # Start jobs
        job_id1 = jm.start_job('simple test',
                               'calibre.srv.jobs',
                               'sleep_test',
                               args=(1.0, ))
        job_id2 = jm.start_job('t2',
                               'calibre.srv.jobs',
                               'sleep_test',
                               args=(3, ))
        job_id3 = jm.start_job('err test', 'calibre.srv.jobs', 'error_test')

        # Job 1
        job_id = job_id1
        status = jm.job_status(job_id)[0]
        self.assertIn(status, s)
        for jid in (job_id2, job_id3):
            self.assertEqual(job_status(jid), 'waiting')
        while job_status(job_id) in s:
            time.sleep(0.01)
        status, result, tb, was_aborted = jm.job_status(job_id)
        self.assertEqual(status, 'finished')
        self.assertFalse(was_aborted)
        self.assertFalse(tb)
        self.assertEqual(result, 1.0)

        # Job 2
        job_id = job_id2
        while job_status(job_id) == 'waiting':
            time.sleep(0.01)
        self.assertEqual('running', job_status(job_id))
        jm.abort_job(job_id)
        self.assertIn(jm.wait_for_running_job(job_id), (True, None))
        status, result, tb, was_aborted = jm.job_status(job_id)
        self.assertEqual('finished', status)
        self.assertTrue(was_aborted)

        # Job 3
        job_id = job_id3
        while job_status(job_id) == 'waiting':
            time.sleep(0.01)
        self.assertIn(jm.wait_for_running_job(job_id), (True, None))
        status, result, tb, was_aborted = jm.job_status(job_id)
        self.assertEqual(status, 'finished')
        self.assertFalse(was_aborted)
        self.assertTrue(tb)
        self.assertIn('a testing error', tb)
        jm.start_job('simple test',
                     'calibre.srv.jobs',
                     'sleep_test',
                     args=(1.0, ))
        jm.shutdown(), jm.wait_for_shutdown(monotonic() + 1)
Ejemplo n.º 35
0
 def on_load_hang(self):
     self.log(
         self.log_prefix,
         'Loading not complete after {} seconds, aborting.'.format(
             int(monotonic() - self.load_started_at)))
     self.load_finished(False)
Ejemplo n.º 36
0
 def startTest(self, test):
     self.start_time[test] = monotonic()
     return super(TestResult, self).startTest(test)
Ejemplo n.º 37
0
 def timed_print(self, *a, **kw):
     if DEBUG:
         prints('[{:.2f}]'.format(monotonic() - self.startup_time), *a, **kw)
Ejemplo n.º 38
0
    def test_http_response(self):  # {{{
        'Test HTTP protocol responses'
        from calibre.srv.http_response import parse_multipart_byterange

        def handler(conn):
            return conn.generate_static_output('test', lambda : ''.join(conn.path))
        with NamedTemporaryFile(suffix='test.epub') as f, open(P('localization/locales.zip'), 'rb') as lf, \
                TestServer(handler, timeout=1, compress_min_size=0) as server:
            fdata = string.ascii_letters * 100
            f.write(fdata), f.seek(0)

            # Test ETag
            conn = server.connect()
            conn.request('GET', '/an_etagged_path')
            r = conn.getresponse()
            self.ae(r.status, httplib.OK), self.ae(r.read(), b'an_etagged_path')
            etag = r.getheader('ETag')
            self.ae(etag, '"%s"' % hashlib.sha1('an_etagged_path').hexdigest())
            conn.request('GET', '/an_etagged_path', headers={'If-None-Match':etag})
            r = conn.getresponse()
            self.ae(r.status, httplib.NOT_MODIFIED)
            self.ae(r.read(), b'')

            # Test gzip
            raw = b'a'*20000
            server.change_handler(lambda conn: raw)
            conn = server.connect()
            conn.request('GET', '/an_etagged_path', headers={'Accept-Encoding':'gzip'})
            r = conn.getresponse()
            self.ae(str(len(raw)), r.getheader('Calibre-Uncompressed-Length'))
            self.ae(r.status, httplib.OK), self.ae(zlib.decompress(r.read(), 16+zlib.MAX_WBITS), raw)

            # Test dynamic etagged content
            num_calls = [0]

            def edfunc():
                num_calls[0] += 1
                return b'data'
            server.change_handler(lambda conn:conn.etagged_dynamic_response("xxx", edfunc))
            conn = server.connect()
            conn.request('GET', '/an_etagged_path')
            r = conn.getresponse()
            self.ae(r.status, httplib.OK), self.ae(r.read(), b'data')
            etag = r.getheader('ETag')
            self.ae(etag, b'"xxx"')
            self.ae(r.getheader('Content-Length'), '4')
            conn.request('GET', '/an_etagged_path', headers={'If-None-Match':etag})
            r = conn.getresponse()
            self.ae(r.status, httplib.NOT_MODIFIED)
            self.ae(r.read(), b'')
            self.ae(num_calls[0], 1)

            # Test getting a filesystem file
            for use_sendfile in (True, False):
                server.change_handler(lambda conn: f)
                server.loop.opts.use_sendfile = use_sendfile
                conn = server.connect()
                conn.request('GET', '/test')
                r = conn.getresponse()
                etag = type('')(r.getheader('ETag'))
                self.assertTrue(etag)
                self.ae(r.getheader('Content-Type'), guess_type(f.name)[0])
                self.ae(type('')(r.getheader('Accept-Ranges')), 'bytes')
                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=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.read(), fdata[2:26])

                conn.request('GET', '/test', headers={'Range':'bytes=100000-'})
                r = conn.getresponse()
                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(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()
                self.ae(r.status, httplib.PARTIAL_CONTENT), self.ae(r.read(), fdata)

                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))

                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))
                buf = BytesIO(data)
                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(timeout=1)
                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)
                time_taken = monotonic() - start_time
                self.assertLess(time_taken, 1, 'Large file transfer took too long')
Ejemplo n.º 39
0
 def wait_for_draw(self):
     # Without this the splash screen is not painted on linux and windows
     self.drawn_once = False
     st = monotonic()
     while not self.drawn_once and (monotonic() - st < 0.1):
         QApplication.instance().processEvents()
Ejemplo n.º 40
0
 def load_progress(self, progress):
     self.last_load_progress_at = monotonic()
Ejemplo n.º 41
0
 def start_print(self):
     margins = QMarginsF(0, 0, 0, 0)
     page_layout = QPageLayout(QPageSize(QPageSize.A4), QPageLayout.Portrait, margins)
     self.printToPdf('rendered.pdf', page_layout)
     self.printing_started = True
     self.start_time = monotonic()
Ejemplo n.º 42
0
 def load_started(self):
     self.load_started_at = monotonic()
     self.load_complete = False
     self.load_hang_check_timer.start()
Ejemplo n.º 43
0
 def start_load(self, path_to_html):
     self.load(QUrl.fromLocalFile(path_to_html))
     self.start_time = monotonic()
     self.hang_timer.start()
Ejemplo n.º 44
0
 def __init__(self, worker, log):
     self.worker, self.log = worker, log
     fpath = os.path.abspath(__file__)
     d = os.path.dirname
     self.base = d(d(d(d(fpath))))
     self.last_restart_time = monotonic()
Ejemplo n.º 45
0
 def get(self, library_id=None):
     try:
         return getattr(LibraryBroker.get(self, library_id), 'new_api', None)
     finally:
         self.last_used_times[library_id or self.default_library] = monotonic()
Ejemplo n.º 46
0
    def tick(self):
        now = monotonic()
        read_needed, write_needed, readable, remove, close_needed = [], [], [], [], []
        has_ssl = self.ssl_context is not None
        for s, conn in iteritems(self.connection_map):
            if now - conn.last_activity > self.opts.timeout:
                if conn.handle_timeout():
                    conn.last_activity = now
                else:
                    remove.append((s, conn))
                    continue
            wf = conn.wait_for
            if wf is READ or wf is RDWR:
                if wf is RDWR:
                    write_needed.append(s)
                if conn.read_buffer.has_data:
                    readable.append(s)
                else:
                    if has_ssl:
                        conn.drain_ssl_buffer()
                        if conn.ready:
                            (readable if conn.read_buffer.has_data else
                             read_needed).append(s)
                        else:
                            close_needed.append((s, conn))
                    else:
                        read_needed.append(s)
            elif wf is WRITE:
                write_needed.append(s)

        for s, conn in remove:
            self.log('Closing connection because of extended inactivity: %s' %
                     conn.state_description)
            self.close(s, conn)

        for x, conn in close_needed:
            self.close(s, conn)

        if readable:
            writable = []
        else:
            try:
                readable, writable, _ = select.select(
                    [self.socket.fileno(),
                     self.control_out.fileno()] + read_needed, write_needed,
                    [], self.opts.timeout)
            except ValueError:  # self.socket.fileno() == -1
                self.ready = False
                self.log.error('Listening socket was unexpectedly terminated')
                return
            except (select.error, socket.error) as e:
                # select.error has no errno attribute. errno is instead
                # e.args[0]
                if getattr(e, 'errno', e.args[0]) in socket_errors_eintr:
                    return
                for s, conn in tuple(iteritems(self.connection_map)):
                    try:
                        select.select([s], [], [], 0)
                    except (select.error, socket.error) as e:
                        if getattr(e, 'errno',
                                   e.args[0]) not in socket_errors_eintr:
                            self.close(s, conn)  # Bad socket, discard
                return

        if not self.ready:
            return

        ignore = set()
        for s, conn, event in self.get_actions(readable, writable):
            if s in ignore:
                continue
            try:
                conn.handle_event(event)
                if not conn.ready:
                    self.close(s, conn)
            except JobQueueFull:
                self.log.exception('Server busy handling request: %s' %
                                   conn.state_description)
                if conn.ready:
                    if conn.response_started:
                        self.close(s, conn)
                    else:
                        try:
                            conn.report_busy()
                        except Exception:
                            self.close(s, conn)
            except Exception as e:
                ignore.add(s)
                ssl_terminated = getattr(conn, 'ssl_terminated', False)
                if ssl_terminated:
                    self.log.warn(
                        'Client tried to initiate SSL renegotiation, closing connection'
                    )
                    self.close(s, conn)
                else:
                    self.log.exception('Unhandled exception in state: %s' %
                                       conn.state_description)
                    if conn.ready:
                        if conn.response_started:
                            self.close(s, conn)
                        else:
                            try:
                                conn.report_unhandled_exception(
                                    e, traceback.format_exc())
                            except Exception:
                                self.close(s, conn)
                    else:
                        self.log.error(
                            'Error in SSL handshake, terminating connection: %s'
                            % as_unicode(e))
                        self.close(s, conn)