diff --git a/couchpotato/cli.py b/couchpotato/cli.py index 9111667..117073b 100644 --- a/couchpotato/cli.py +++ b/couchpotato/cli.py @@ -2,7 +2,7 @@ from argparse import ArgumentParser from couchpotato import web from couchpotato.api import api from couchpotato.core.event import fireEventAsync -from libs.daemon import createDaemon +from daemon import createDaemon from logging import handlers from werkzeug.contrib.cache import FileSystemCache import logging @@ -67,36 +67,37 @@ def cmd_couchpotato(options, base_path, args): debug = options.debug or Env.setting('debug', default = False) Env.set('debug', debug) + # Only run once when debugging + if os.environ.get('WERKZEUG_RUN_MAIN') or not debug: - # Logger - logger = logging.getLogger() - formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s', '%H:%M:%S') - level = logging.DEBUG if debug else logging.INFO - logger.setLevel(level) + # Logger + logger = logging.getLogger() + formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s', '%H:%M:%S') + level = logging.DEBUG if debug else logging.INFO + logger.setLevel(level) - # To screen - if debug and not options.quiet and not options.daemonize: - hdlr = logging.StreamHandler(sys.stderr) - hdlr.setFormatter(formatter) - logger.addHandler(hdlr) + # To screen + if debug and not options.quiet and not options.daemonize: + hdlr = logging.StreamHandler(sys.stderr) + hdlr.setFormatter(formatter) + logger.addHandler(hdlr) - # To file - hdlr2 = handlers.RotatingFileHandler(Env.get('log_path'), 'a', 500000, 10) - hdlr2.setFormatter(formatter) - logger.addHandler(hdlr2) + # To file + hdlr2 = handlers.RotatingFileHandler(Env.get('log_path'), 'a', 500000, 10) + hdlr2.setFormatter(formatter) + logger.addHandler(hdlr2) - # Disable server access log - server_log = logging.getLogger('werkzeug') - server_log.disabled = True + # Disable server access log + server_log = logging.getLogger('werkzeug') + server_log.disabled = True - # Start logging - from couchpotato.core.logger import CPLog - log = CPLog(__name__) - log.debug('Started with options %s' % options) + # Start logging + from couchpotato.core.logger import CPLog + log = CPLog(__name__) + log.debug('Started with options %s' % options) - # Load configs & plugins (only run once when debugging) - if os.environ.get('WERKZEUG_RUN_MAIN') or not debug: + # Load configs & plugins loader = Env.get('loader') loader.preload(root = base_path) loader.run() diff --git a/couchpotato/core/_base/_core/main.py b/couchpotato/core/_base/_core/main.py index 2474685..5423aa8 100644 --- a/couchpotato/core/_base/_core/main.py +++ b/couchpotato/core/_base/_core/main.py @@ -5,6 +5,7 @@ from couchpotato.core.plugins.base import Plugin from couchpotato.environment import Env from flask import request import os +import time log = CPLog(__name__) @@ -29,12 +30,25 @@ class Core(Plugin): fireEvent('app.shutdown') + while 1: + still_running = fireEvent('plugin.running') + + brk = True + for running in still_running: + if running > 0: + brk = False + + if brk: break + + time.sleep(1) + + if restart: - self.writeRestartFile() + self.createFile(self.restartFilePath(), 'This is the most suckiest way to register if CP is restarted. Ever...') func = request.environ.get('werkzeug.server.shutdown') if func is None: - raise RuntimeError('Not running with the Werkzeug Server') + log.error('Failed shutting down the server') func() def removeRestartFile(self): @@ -43,12 +57,5 @@ class Core(Plugin): except: pass - def writeRestartFile(self): - try: - with open(self.restartFilePath(), 'w') as f: - f.write('This is the most suckiest way to register if CP is restarted. Ever...') - except Exception, e: - log.error('Could not write shutdown file: %s' % e) - def restartFilePath(self): return os.path.join(Env.get('data_dir'), 'restart') diff --git a/couchpotato/core/event.py b/couchpotato/core/event.py index 829d664..caffd65 100644 --- a/couchpotato/core/event.py +++ b/couchpotato/core/event.py @@ -1,12 +1,16 @@ from axl.axel import Event from couchpotato.core.helpers.variable import mergeDicts from couchpotato.core.logger import CPLog +import inspect import threading import traceback log = CPLog(__name__) events = {} + + + def addEvent(name, handler): if events.get(name): @@ -14,7 +18,14 @@ def addEvent(name, handler): else: e = events[name] = Event(threads = 20, exc_info = True, traceback = True, lock = threading.RLock()) - e += handler + def createHandle(handler, *args, **kwargs): + handler.im_self.isRunning(True) + h = handler(*args, **kwargs) + handler.im_self.isRunning(True) + + return h + + e += createHandle(handler) def removeEvent(name, handler): e = events[name] diff --git a/couchpotato/core/plugins/base.py b/couchpotato/core/plugins/base.py index 6c2321e..fa06e9f 100644 --- a/couchpotato/core/plugins/base.py +++ b/couchpotato/core/plugins/base.py @@ -17,9 +17,11 @@ class Plugin(object): auto_register_static = True needs_shutdown = False + running = 0 def registerPlugin(self): addEvent('app.shutdown', self.doShutdown) + addEvent('plugin.running', self.isRunning) def conf(self, attr, default = None): return Env.setting(attr, self.getName().lower(), default = default) @@ -40,21 +42,21 @@ class Plugin(object): addView(path + '', self.showStatic, static = True) if add_to_head: - for file in glob.glob(os.path.join(self.plugin_path, 'static', '*')): - fireEvent('register_%s' % ('script' if getExt(file) in 'js' else 'style'), path + os.path.basename(file)) + for f in glob.glob(os.path.join(self.plugin_path, 'static', '*')): + fireEvent('register_%s' % ('script' if getExt(f) in 'js' else 'style'), path + os.path.basename(f)) - def showStatic(self, file = ''): - dir = os.path.join(self.plugin_path, 'static') - return send_from_directory(dir, file) + def showStatic(self, f = ''): + d = os.path.join(self.plugin_path, 'static') + return send_from_directory(d, f) def createFile(self, path, content): self.makeDir(os.path.dirname(path)) try: - file = open(path, 'w') - file.write(content) - file.close() + f = open(path, 'w') + f.write(content) + f.close() except Exception, e: log.error('Unable writing to file "%s": %s' % (path, e)) @@ -75,6 +77,13 @@ class Plugin(object): self.needs_shutdown = value + def isRunning(self, value = None): + if value is None: + return self.running + + log.debug('Running %s: %s' % (value, self.getName())) + self.running += 1 if value else -1 + def isDisabled(self): return not self.isEnabled() diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index e52b68c..04bfa7f 100644 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -216,6 +216,10 @@ class Renamer(Plugin): # Search for trailers etc fireEvent('renamer.after', group) + # Break if CP wants to shut down + if self.shuttingDown(): + break + def moveFile(self, old, dest, suppress = True): try: shutil.move(old, dest) diff --git a/couchpotato/core/plugins/searcher/main.py b/couchpotato/core/plugins/searcher/main.py index 7330a1d..bef8faa 100644 --- a/couchpotato/core/plugins/searcher/main.py +++ b/couchpotato/core/plugins/searcher/main.py @@ -30,6 +30,7 @@ class Searcher(Plugin): ).all() for movie in movies: + self.single(movie.to_dict(deep = { 'profile': {'types': {'quality': {}}}, 'releases': {'status': {}, 'quality': {}}, @@ -37,6 +38,10 @@ class Searcher(Plugin): 'files': {} })) + # Break if CP wants to shut down + if self.shuttingDown(): + break + def single(self, movie): downloaded_status = fireEvent('status.get', 'downloaded', single = True)