%PDF- %PDF-
| Direktori : /lib/calibre/calibre/srv/ |
| Current File : //lib/calibre/calibre/srv/embedded.py |
#!/usr/bin/env python3
# License: GPLv3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
import errno
import json
import os
from contextlib import suppress
from threading import Thread
from calibre import as_unicode
from calibre.constants import cache_dir, config_dir, is_running_from_develop
from calibre.srv.bonjour import BonJour
from calibre.srv.handler import Handler
from calibre.srv.http_response import create_http_handler
from calibre.srv.loop import ServerLoop
from calibre.srv.opts import server_config
from calibre.srv.utils import RotatingLog
def log_paths():
return os.path.join(cache_dir(), 'server-log.txt'), os.path.join(
cache_dir(), 'server-access-log.txt'
)
def read_json(path):
try:
with lopen(path, 'rb') as f:
raw = f.read()
except OSError as err:
if err.errno != errno.ENOENT:
raise
return
with suppress(json.JSONDecodeError):
return json.loads(raw)
def custom_list_template():
return read_json(custom_list_template.path)
def search_the_net_urls():
return read_json(search_the_net_urls.path)
custom_list_template.path = os.path.join(config_dir, 'server-custom-list-template.json')
search_the_net_urls.path = os.path.join(config_dir, 'server-search-the-net.json')
class Server:
loop = current_thread = exception = None
state_callback = start_failure_callback = None
def __init__(self, library_broker, notify_changes):
opts = server_config()
lp, lap = log_paths()
try:
os.makedirs(cache_dir())
except OSError as err:
if err.errno != errno.EEXIST:
raise
log_size = opts.max_log_size * 1024 * 1024
log = RotatingLog(lp, max_size=log_size)
access_log = RotatingLog(lap, max_size=log_size)
self.handler = Handler(library_broker, opts, notify_changes=notify_changes)
plugins = self.plugins = []
if opts.use_bonjour:
plugins.append(BonJour(wait_for_stop=max(0, opts.shutdown_timeout - 0.2)))
self.opts = opts
self.log, self.access_log = log, access_log
self.handler.set_log(self.log)
self.handler.router.ctx.custom_list_template = custom_list_template()
self.handler.router.ctx.search_the_net_urls = search_the_net_urls()
@property
def ctx(self):
return self.handler.router.ctx
@property
def user_manager(self):
return self.handler.router.ctx.user_manager
def start(self):
if self.current_thread is None:
try:
self.loop = ServerLoop(
create_http_handler(self.handler.dispatch),
opts=self.opts,
log=self.log,
access_log=self.access_log,
plugins=self.plugins
)
self.loop.initialize_socket()
except Exception as e:
self.loop = None
self.exception = e
if self.start_failure_callback is not None:
try:
self.start_failure_callback(as_unicode(e))
except Exception:
pass
return
self.handler.set_jobs_manager(self.loop.jobs_manager)
self.current_thread = t = Thread(
name='EmbeddedServer', target=self.serve_forever
)
t.daemon = True
t.start()
def serve_forever(self):
self.exception = None
from calibre.srv.content import reset_caches
try:
if is_running_from_develop:
from calibre.utils.rapydscript import compile_srv
compile_srv()
except BaseException as e:
self.exception = e
if self.start_failure_callback is not None:
try:
self.start_failure_callback(as_unicode(e))
except Exception:
pass
return
if self.state_callback is not None:
try:
self.state_callback(True)
except Exception:
pass
reset_caches() # we reset the cache as the server tdir has changed
try:
self.loop.serve_forever()
except BaseException as e:
self.exception = e
if self.state_callback is not None:
try:
self.state_callback(False)
except Exception:
pass
def stop(self):
if self.loop is not None:
self.loop.stop()
self.loop = None
def exit(self):
if self.current_thread is not None:
self.stop()
self.current_thread.join()
self.current_thread = None
@property
def is_running(self):
return self.current_thread is not None and self.current_thread.is_alive()