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()
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')
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)
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
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)
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)
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)
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()
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)
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)
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)
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
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)
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
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
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
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
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
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
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()
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()
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()
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)
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()
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))
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)
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)
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]
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
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)
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()
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()
def force_restart(self): self.worker.restart(forced=True) self.last_restart_time = monotonic()
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)
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)
def startTest(self, test): self.start_time[test] = monotonic() return super(TestResult, self).startTest(test)
def timed_print(self, *a, **kw): if DEBUG: prints('[{:.2f}]'.format(monotonic() - self.startup_time), *a, **kw)
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')
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()
def load_progress(self, progress): self.last_load_progress_at = monotonic()
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()
def load_started(self): self.load_started_at = monotonic() self.load_complete = False self.load_hang_check_timer.start()
def start_load(self, path_to_html): self.load(QUrl.fromLocalFile(path_to_html)) self.start_time = monotonic() self.hang_timer.start()
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()
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()
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)