Shutdown event
This commit is contained in:
+31
-30
@@ -2,7 +2,7 @@ from argparse import ArgumentParser
|
|||||||
from couchpotato import web
|
from couchpotato import web
|
||||||
from couchpotato.api import api
|
from couchpotato.api import api
|
||||||
from couchpotato.core.event import fireEventAsync
|
from couchpotato.core.event import fireEventAsync
|
||||||
from libs.daemon import createDaemon
|
from daemon import createDaemon
|
||||||
from logging import handlers
|
from logging import handlers
|
||||||
from werkzeug.contrib.cache import FileSystemCache
|
from werkzeug.contrib.cache import FileSystemCache
|
||||||
import logging
|
import logging
|
||||||
@@ -67,36 +67,37 @@ def cmd_couchpotato(options, base_path, args):
|
|||||||
debug = options.debug or Env.setting('debug', default = False)
|
debug = options.debug or Env.setting('debug', default = False)
|
||||||
Env.set('debug', debug)
|
Env.set('debug', debug)
|
||||||
|
|
||||||
|
# Only run once when debugging
|
||||||
# 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 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
|
|
||||||
|
|
||||||
# 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:
|
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)
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
|
||||||
|
# Load configs & plugins
|
||||||
loader = Env.get('loader')
|
loader = Env.get('loader')
|
||||||
loader.preload(root = base_path)
|
loader.preload(root = base_path)
|
||||||
loader.run()
|
loader.run()
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from couchpotato.core.plugins.base import Plugin
|
|||||||
from couchpotato.environment import Env
|
from couchpotato.environment import Env
|
||||||
from flask import request
|
from flask import request
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
log = CPLog(__name__)
|
log = CPLog(__name__)
|
||||||
@@ -29,12 +30,25 @@ class Core(Plugin):
|
|||||||
|
|
||||||
fireEvent('app.shutdown')
|
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:
|
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')
|
func = request.environ.get('werkzeug.server.shutdown')
|
||||||
if func is None:
|
if func is None:
|
||||||
raise RuntimeError('Not running with the Werkzeug Server')
|
log.error('Failed shutting down the server')
|
||||||
func()
|
func()
|
||||||
|
|
||||||
def removeRestartFile(self):
|
def removeRestartFile(self):
|
||||||
@@ -43,12 +57,5 @@ class Core(Plugin):
|
|||||||
except:
|
except:
|
||||||
pass
|
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):
|
def restartFilePath(self):
|
||||||
return os.path.join(Env.get('data_dir'), 'restart')
|
return os.path.join(Env.get('data_dir'), 'restart')
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
from axl.axel import Event
|
from axl.axel import Event
|
||||||
from couchpotato.core.helpers.variable import mergeDicts
|
from couchpotato.core.helpers.variable import mergeDicts
|
||||||
from couchpotato.core.logger import CPLog
|
from couchpotato.core.logger import CPLog
|
||||||
|
import inspect
|
||||||
import threading
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
log = CPLog(__name__)
|
log = CPLog(__name__)
|
||||||
events = {}
|
events = {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def addEvent(name, handler):
|
def addEvent(name, handler):
|
||||||
|
|
||||||
if events.get(name):
|
if events.get(name):
|
||||||
@@ -14,7 +18,14 @@ def addEvent(name, handler):
|
|||||||
else:
|
else:
|
||||||
e = events[name] = Event(threads = 20, exc_info = True, traceback = True, lock = threading.RLock())
|
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):
|
def removeEvent(name, handler):
|
||||||
e = events[name]
|
e = events[name]
|
||||||
|
|||||||
@@ -17,9 +17,11 @@ class Plugin(object):
|
|||||||
auto_register_static = True
|
auto_register_static = True
|
||||||
|
|
||||||
needs_shutdown = False
|
needs_shutdown = False
|
||||||
|
running = 0
|
||||||
|
|
||||||
def registerPlugin(self):
|
def registerPlugin(self):
|
||||||
addEvent('app.shutdown', self.doShutdown)
|
addEvent('app.shutdown', self.doShutdown)
|
||||||
|
addEvent('plugin.running', self.isRunning)
|
||||||
|
|
||||||
def conf(self, attr, default = None):
|
def conf(self, attr, default = None):
|
||||||
return Env.setting(attr, self.getName().lower(), default = default)
|
return Env.setting(attr, self.getName().lower(), default = default)
|
||||||
@@ -40,21 +42,21 @@ class Plugin(object):
|
|||||||
addView(path + '<path:file>', self.showStatic, static = True)
|
addView(path + '<path:file>', self.showStatic, static = True)
|
||||||
|
|
||||||
if add_to_head:
|
if add_to_head:
|
||||||
for file in glob.glob(os.path.join(self.plugin_path, 'static', '*')):
|
for f 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))
|
fireEvent('register_%s' % ('script' if getExt(f) in 'js' else 'style'), path + os.path.basename(f))
|
||||||
|
|
||||||
def showStatic(self, file = ''):
|
def showStatic(self, f = ''):
|
||||||
dir = os.path.join(self.plugin_path, 'static')
|
d = os.path.join(self.plugin_path, 'static')
|
||||||
return send_from_directory(dir, file)
|
return send_from_directory(d, f)
|
||||||
|
|
||||||
def createFile(self, path, content):
|
def createFile(self, path, content):
|
||||||
|
|
||||||
self.makeDir(os.path.dirname(path))
|
self.makeDir(os.path.dirname(path))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
file = open(path, 'w')
|
f = open(path, 'w')
|
||||||
file.write(content)
|
f.write(content)
|
||||||
file.close()
|
f.close()
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
log.error('Unable writing to file "%s": %s' % (path, e))
|
log.error('Unable writing to file "%s": %s' % (path, e))
|
||||||
|
|
||||||
@@ -75,6 +77,13 @@ class Plugin(object):
|
|||||||
|
|
||||||
self.needs_shutdown = value
|
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):
|
def isDisabled(self):
|
||||||
return not self.isEnabled()
|
return not self.isEnabled()
|
||||||
|
|
||||||
|
|||||||
@@ -216,6 +216,10 @@ class Renamer(Plugin):
|
|||||||
# Search for trailers etc
|
# Search for trailers etc
|
||||||
fireEvent('renamer.after', group)
|
fireEvent('renamer.after', group)
|
||||||
|
|
||||||
|
# Break if CP wants to shut down
|
||||||
|
if self.shuttingDown():
|
||||||
|
break
|
||||||
|
|
||||||
def moveFile(self, old, dest, suppress = True):
|
def moveFile(self, old, dest, suppress = True):
|
||||||
try:
|
try:
|
||||||
shutil.move(old, dest)
|
shutil.move(old, dest)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class Searcher(Plugin):
|
|||||||
).all()
|
).all()
|
||||||
|
|
||||||
for movie in movies:
|
for movie in movies:
|
||||||
|
|
||||||
self.single(movie.to_dict(deep = {
|
self.single(movie.to_dict(deep = {
|
||||||
'profile': {'types': {'quality': {}}},
|
'profile': {'types': {'quality': {}}},
|
||||||
'releases': {'status': {}, 'quality': {}},
|
'releases': {'status': {}, 'quality': {}},
|
||||||
@@ -37,6 +38,10 @@ class Searcher(Plugin):
|
|||||||
'files': {}
|
'files': {}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
# Break if CP wants to shut down
|
||||||
|
if self.shuttingDown():
|
||||||
|
break
|
||||||
|
|
||||||
def single(self, movie):
|
def single(self, movie):
|
||||||
|
|
||||||
downloaded_status = fireEvent('status.get', 'downloaded', single = True)
|
downloaded_status = fireEvent('status.get', 'downloaded', single = True)
|
||||||
|
|||||||
Reference in New Issue
Block a user