# we use Medusa's logger if logfilename: lgr = logger.file_logger (logfilename) else: # This will log to an overhead subdirectory of the repository logfile_directory = os.path.join(directory, "overhead") if not os.path.exists(logfile_directory): os.makedirs(logfile_directory) lgr = thread_safe_rotating_file_logger (os.path.join(logfile_directory, "angel.log"), "weekly", 10*1024*1024, true) # make sure anything written with note() will go to the logfile set_note_sink(lgr) repo, use_ssl, ip_addr, conf = Repository.build_world(directory, portno, logfilename) note(0, "repo is %s, use_ssl is %s, ip_addr is %s, conf is %s", repo, use_ssl, ip_addr, conf) ############################################################ ### ### check for pending documents, and start them ### ############################################################ retry_folders (repo) ############################################################ ### ### get the web server running
def start_angel(directory, portno, logfilename=None): from uplib.plibUtil import note, configurator, set_note_sink from uplib.tornadoHandler import ActionHandler, PingHandler, DocsHandler, LoginHandler from uplib.repository import Repository from uplib.newFolder import retry_folders ############################################################ ### ### create the repo and run initializers ### ############################################################ # set up logging rootlogger = logging.getLogger() if logfilename: rootlogger.addHandler( logging.handlers.RotatingFileHandler(logfilename, "a", 10 * 1024 * 1024, 10 * 1024 * 1024) ) else: # This will log to an overhead subdirectory of the repository logfile_directory = os.path.join(directory, "overhead") if not os.path.exists(logfile_directory): os.makedirs(logfile_directory) rootlogger.addHandler( logging.handlers.RotatingFileHandler( os.path.join(logfile_directory, "angel.log"), "a", 10 * 1024 * 1024, 10 * 1024 * 1024 ) ) # filter out logging of repo_status_json calls, which occur frequently class RepoStatusJsonFilter(logging.Filter): def filter(self, record): text = (record.args and str(record.msg) % record.args) or record.msg return "/action/basic/repo_status_json" not in text rootlogger.addFilter(RepoStatusJsonFilter()) # make sure anything written with note() will go to the logfile set_note_sink(rootlogger) repo, use_ssl, ip_addr, conf = Repository.build_world(directory, portno, logfilename) note("using IP address %s, use_ssl is %s", ip_addr, use_ssl) ############################################################ ### ### check for pending documents, and start them ### ############################################################ retry_folders(repo) ############################################################ ### ### Now create the Tornado app... ### ############################################################ transforms = list() transforms.append(tornado.web.GZipContentEncoding) # see if we should use chunking in our server replies use_chunking = not conf.get_bool("no-server-chunking", False) if not use_chunking: note("disabling server HTTP 1.1 reply chunking") else: transforms.append(tornado.web.ChunkedTransferEncoding) handlers = list() # This handler handles extension requests handlers.append(("/action/(.*)", ActionHandler, {"repository": repo})) # Redirect "/" to the top-level root handlers.append(("/", ActionHandler, {"repository": repo})) # This handler simply replys OK to a request for /ping, to indicate that # the server is alive and OK, and for /login, to establish authorization # credentials handlers.append(("/ping", PingHandler, {"repository": repo})) handlers.append(("/favicon.ico", PingHandler, {"repository": repo})) handlers.append(("/html/signedreadup.jar", PingHandler, {"repository": repo})) handlers.append(("/html/images/ReadUpJWS.gif", PingHandler, {"repository": repo})) # The folder handler is the class which delivers documents from the docs # subdirectory requested directly, such as thumbnails. handlers.append(("/docs/(.*)", DocsHandler, {"repository": repo, "allow-caching": conf.get_bool("allow-caching")})) # this handler serves up static HTML, jars, and images from under /html/ handlers.append(("/html/(.*)", tornado.web.StaticFileHandler, {"path": os.path.join(repo.root(), "html")})) # use LoginHandler to handle login authorization handlers.append(("/login", LoginHandler, {"repository": repo})) # now set up server if use_ssl: import ssl ssl_options = {"certfile": os.path.normpath(repo.certfilename())} root_certs_file = conf.get("root-certificates-file") if root_certs_file: if not os.path.exists(root_certs_file): sys.stderr.write("specified root-certificates-file %s does not exist!\n" % root_certs_file) sys.exit(1) else: ssl_options["ca_certs"] = root_certs_file ssl_options["cert_reqs"] = ssl.CERT_REQUIRED else: ssl_options = None try: http_server = tornado.httpserver.HTTPServer( tornado.web.Application(handlers=handlers, transforms=transforms), ssl_options=ssl_options ) http_server.listen(repo.port(), ip_addr) note("Now listening at %s://%s:%s" % ((ssl_options and "https") or "http", ip_addr, repo.port())) except: type, value, tb = sys.exc_info() s = "".join(traceback.format_exception(type, value, tb)) note("Can't establish HTTP server: exception: " + s) note("Abandoning attempt to start this daemon...") os._exit(1) # kill other subprocesses when exiting if not sys.platform.lower().startswith("win"): import signal def kill_subprocs(): gid = os.getpgrp() note(0, "killing subprocesses in process group %s...", gid) os.killpg(-gid, signal.SIGTERM) atexit.register(kill_subprocs) # shutdown the server cleanly if things exit atexit.register(lambda x=http_server: x.close()) # call the repo shutdown if the service exits atexit.register(lambda x=repo: x.shutdown(0)) # # Catch various termination signals and save state cleanly # if not sys.platform.lower().startswith("win"): import signal signal.signal(signal.SIGTERM, lambda signum, frame: (note(0, "SIGTERM received, exiting..."), sys.exit(0))) signal.signal(signal.SIGUSR1, lambda signum, frame: (note(0, "SIGUSR1 received, saving..."), repo.save(true))) note(0, "------- Restarted at %s. ----------", time.ctime()) # touch flag file to signal watchers... open(os.path.join(repo.root(), "overhead", "angel.started"), "w").write(str(time.time())) return repo