mirror of
https://github.com/moparisthebest/SickRage
synced 2024-12-12 11:02:21 -05:00
New event queue system in place, currently handles shutdown and restart calls.
Fixed ctrl-c issues with new event queue system. Added a sleep timer to the NameParser class to help lower cpu usage spikes.
This commit is contained in:
parent
0866bcc344
commit
74f73bcc34
108
SickBeard.py
108
SickBeard.py
@ -21,6 +21,7 @@
|
||||
from __future__ import with_statement
|
||||
|
||||
import time
|
||||
import signal
|
||||
import sys
|
||||
import shutil
|
||||
import subprocess
|
||||
@ -52,12 +53,12 @@ if sys.hexversion >= 0x020600F0:
|
||||
import locale
|
||||
import datetime
|
||||
import threading
|
||||
import signal
|
||||
import traceback
|
||||
import getopt
|
||||
|
||||
import sickbeard
|
||||
|
||||
from sickbeard.event_queue import Events
|
||||
from sickbeard import db
|
||||
from sickbeard.tv import TVShow
|
||||
from sickbeard import logger, network_timezones, failed_history, name_cache
|
||||
@ -68,14 +69,16 @@ from sickbeard.databases.mainDB import MAX_DB_VERSION
|
||||
|
||||
from lib.configobj import ConfigObj
|
||||
|
||||
throwaway = datetime.datetime.strptime('20110101', '%Y%m%d')
|
||||
|
||||
signal.signal(signal.SIGINT, sickbeard.sig_handler)
|
||||
signal.signal(signal.SIGTERM, sickbeard.sig_handler)
|
||||
|
||||
throwaway = datetime.datetime.strptime('20110101', '%Y%m%d')
|
||||
|
||||
class SickRage(object):
|
||||
|
||||
def __init__(self):
|
||||
sickbeard.events = Events(self.shutdown)
|
||||
|
||||
self.webserver = None
|
||||
self.runAsDaemon = False
|
||||
self.CREATEPID = False
|
||||
@ -330,7 +333,8 @@ class SickRage(object):
|
||||
if sickbeard.LAUNCH_BROWSER and not (self.noLaunch or self.runAsDaemon):
|
||||
sickbeard.launchBrowser(self.startPort)
|
||||
|
||||
while(sickbeard.started):
|
||||
# main loop
|
||||
while(True):
|
||||
time.sleep(1)
|
||||
|
||||
def daemonize(self):
|
||||
@ -431,56 +435,54 @@ class SickRage(object):
|
||||
except:
|
||||
return False
|
||||
|
||||
def shutdown(self, type):
|
||||
if sickbeard.started:
|
||||
# stop all tasks
|
||||
sickbeard.halt()
|
||||
|
||||
# shutdown web server
|
||||
if self.webserver:
|
||||
self.webserver.shutDown()
|
||||
self.webserver = None
|
||||
|
||||
# save all shows to DB
|
||||
sickbeard.saveAll()
|
||||
|
||||
# if run as daemon delete the pidfile
|
||||
if self.runAsDaemon and self.CREATEPID:
|
||||
self.remove_pid_file(self.PIDFILE)
|
||||
|
||||
if type == sickbeard.events.SystemEvent.RESTART:
|
||||
install_type = sickbeard.versionCheckScheduler.action.install_type
|
||||
|
||||
popen_list = []
|
||||
|
||||
if install_type in ('git', 'source'):
|
||||
popen_list = [sys.executable, sickbeard.MY_FULLNAME]
|
||||
elif install_type == 'win':
|
||||
if hasattr(sys, 'frozen'):
|
||||
# c:\dir\to\updater.exe 12345 c:\dir\to\sickbeard.exe
|
||||
popen_list = [os.path.join(sickbeard.PROG_DIR, 'updater.exe'), str(sickbeard.PID), sys.executable]
|
||||
else:
|
||||
logger.log(u"Unknown SB launch method, please file a bug report about this", logger.ERROR)
|
||||
popen_list = [sys.executable, os.path.join(sickbeard.PROG_DIR, 'updater.py'), str(sickbeard.PID),
|
||||
sys.executable,
|
||||
sickbeard.MY_FULLNAME]
|
||||
|
||||
if popen_list:
|
||||
popen_list += sickbeard.MY_ARGS
|
||||
if '--nolaunch' not in popen_list:
|
||||
popen_list += ['--nolaunch']
|
||||
logger.log(u"Restarting SickRage with " + str(popen_list))
|
||||
logger.close()
|
||||
subprocess.Popen(popen_list, cwd=os.getcwd())
|
||||
|
||||
# system exit
|
||||
os._exit(0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
if sys.hexversion >= 0x020600F0:
|
||||
freeze_support()
|
||||
|
||||
sr = None
|
||||
try:
|
||||
# init sickrage
|
||||
sr = SickRage()
|
||||
|
||||
# start sickrage
|
||||
sr.start()
|
||||
|
||||
# shutdown web server
|
||||
sr.webserver.shutDown()
|
||||
sr.webserver.join()
|
||||
sr.webserver = None
|
||||
|
||||
# if run as daemon delete the pidfile
|
||||
if sr.runAsDaemon and sr.CREATEPID:
|
||||
sr.remove_pid_file(sr.PIDFILE)
|
||||
|
||||
if not sickbeard.shutdown:
|
||||
install_type = sickbeard.versionCheckScheduler.action.install_type
|
||||
|
||||
popen_list = []
|
||||
|
||||
if install_type in ('git', 'source'):
|
||||
popen_list = [sys.executable, sickbeard.MY_FULLNAME]
|
||||
elif install_type == 'win':
|
||||
if hasattr(sys, 'frozen'):
|
||||
# c:\dir\to\updater.exe 12345 c:\dir\to\sickbeard.exe
|
||||
popen_list = [os.path.join(sickbeard.PROG_DIR, 'updater.exe'), str(sickbeard.PID), sys.executable]
|
||||
else:
|
||||
logger.log(u"Unknown SB launch method, please file a bug report about this", logger.ERROR)
|
||||
popen_list = [sys.executable, os.path.join(sickbeard.PROG_DIR, 'updater.py'), str(sickbeard.PID), sys.executable,
|
||||
sickbeard.MY_FULLNAME]
|
||||
|
||||
if popen_list:
|
||||
popen_list += sickbeard.MY_ARGS
|
||||
if '--nolaunch' not in popen_list:
|
||||
popen_list += ['--nolaunch']
|
||||
logger.log(u"Restarting SickRage with " + str(popen_list))
|
||||
logger.close()
|
||||
subprocess.Popen(popen_list, cwd=os.getcwd())
|
||||
|
||||
# exit process
|
||||
os._exit(0)
|
||||
except:
|
||||
if sr:
|
||||
logger.log(traceback.format_exc(), logger.ERROR)
|
||||
else:
|
||||
print(traceback.format_exc())
|
||||
sys.exit(1)
|
||||
# start sickrage
|
||||
SickRage().start()
|
@ -49,7 +49,6 @@ from sickbeard.common import SD, SKIPPED, NAMING_REPEAT
|
||||
from sickbeard.databases import mainDB, cache_db, failed_db
|
||||
|
||||
from lib.configobj import ConfigObj
|
||||
from tornado.ioloop import IOLoop
|
||||
import xml.etree.ElementTree as ElementTree
|
||||
|
||||
PID = None
|
||||
@ -75,6 +74,9 @@ PIDFILE = ''
|
||||
DAEMON = None
|
||||
NO_RESIZE = False
|
||||
|
||||
# system events
|
||||
events = None
|
||||
|
||||
dailySearchScheduler = None
|
||||
backlogSearchScheduler = None
|
||||
showUpdateScheduler = None
|
||||
@ -103,7 +105,6 @@ CUR_COMMIT_HASH = None
|
||||
|
||||
INIT_LOCK = Lock()
|
||||
started = False
|
||||
shutdown = False
|
||||
|
||||
ACTUAL_LOG_DIR = None
|
||||
LOG_DIR = None
|
||||
@ -1166,7 +1167,7 @@ def halt():
|
||||
showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \
|
||||
properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \
|
||||
subtitlesFinderScheduler, traktCheckerScheduler, \
|
||||
dailySearchScheduler, started
|
||||
dailySearchScheduler, events, started
|
||||
|
||||
with INIT_LOCK:
|
||||
|
||||
@ -1174,7 +1175,12 @@ def halt():
|
||||
|
||||
logger.log(u"Aborting all threads")
|
||||
|
||||
# abort all the threads
|
||||
events.alive = False
|
||||
logger.log(u"Waiting for the EVENTS thread to exit")
|
||||
try:
|
||||
events.join(10)
|
||||
except:
|
||||
pass
|
||||
|
||||
dailySearchScheduler.abort = True
|
||||
logger.log(u"Waiting for the DAILYSEARCH thread to exit")
|
||||
@ -1261,7 +1267,7 @@ def halt():
|
||||
def sig_handler(signum=None, frame=None):
|
||||
if type(signum) != type(None):
|
||||
logger.log(u"Signal %i caught, saving and exiting..." % int(signum))
|
||||
saveAndShutdown()
|
||||
events.put(events.SystemEvent.SHUTDOWN)
|
||||
|
||||
def saveAll():
|
||||
global showList
|
||||
@ -1275,32 +1281,6 @@ def saveAll():
|
||||
logger.log(u"Saving config file to disk")
|
||||
save_config()
|
||||
|
||||
def saveAndShutdown(restart=False):
|
||||
global shutdown, started
|
||||
|
||||
# flag restart/shutdown
|
||||
if not restart:
|
||||
shutdown = True
|
||||
|
||||
# proceed with shutdown
|
||||
started = False
|
||||
|
||||
def invoke_command(to_call, *args, **kwargs):
|
||||
|
||||
def delegate():
|
||||
to_call(*args, **kwargs)
|
||||
|
||||
logger.log(u"Placed invoked command: " + repr(delegate) + " for " + repr(to_call) + " with " + repr(
|
||||
args) + " and " + repr(kwargs), logger.DEBUG)
|
||||
|
||||
IOLoop.current().add_callback(delegate)
|
||||
|
||||
def invoke_restart(soft=True):
|
||||
invoke_command(restart, soft=soft)
|
||||
|
||||
def invoke_shutdown():
|
||||
invoke_command(saveAndShutdown, False)
|
||||
|
||||
def restart(soft=True):
|
||||
if soft:
|
||||
halt()
|
||||
@ -1308,7 +1288,7 @@ def restart(soft=True):
|
||||
logger.log(u"Re-initializing all data")
|
||||
initialize()
|
||||
else:
|
||||
saveAndShutdown(True)
|
||||
events.put(events.SystemEvent.RESTART)
|
||||
|
||||
|
||||
def save_config():
|
||||
|
45
sickbeard/event_queue.py
Normal file
45
sickbeard/event_queue.py
Normal file
@ -0,0 +1,45 @@
|
||||
from threading import Thread
|
||||
from Queue import Queue, Empty
|
||||
from tornado.ioloop import IOLoop
|
||||
|
||||
class Event:
|
||||
def __init__(self, type):
|
||||
self._type = type
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self._type
|
||||
|
||||
class Events(Thread):
|
||||
def __init__(self, callback):
|
||||
super(Events, self).__init__()
|
||||
self.queue = Queue()
|
||||
self.daemon = True
|
||||
self.alive = True
|
||||
self.callback = callback
|
||||
self.name = "EVENT-QUEUE"
|
||||
|
||||
# auto-start
|
||||
self.start()
|
||||
|
||||
def put(self, type):
|
||||
self.queue.put_nowait(type)
|
||||
|
||||
def run(self):
|
||||
while(self.alive):
|
||||
try:
|
||||
# get event type
|
||||
type = self.queue.get(True, 1)
|
||||
|
||||
# perform callback if we got a event type
|
||||
self.callback(type)
|
||||
|
||||
# event completed
|
||||
self.queue.task_done()
|
||||
except Empty:
|
||||
type = None
|
||||
|
||||
# System Events
|
||||
class SystemEvent(Event):
|
||||
RESTART = "RESTART"
|
||||
SHUTDOWN = "SHUTDOWN"
|
@ -16,6 +16,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with SickRage. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import time
|
||||
import re
|
||||
import datetime
|
||||
import os.path
|
||||
@ -133,6 +134,8 @@ class NameParser(object):
|
||||
if self.showObj:
|
||||
break
|
||||
else:
|
||||
time.sleep(0.05)
|
||||
|
||||
raise InvalidShowException(
|
||||
"Unable to parse " + name.encode(sickbeard.SYS_ENCODING, 'xmlcharrefreplace'))
|
||||
|
||||
@ -251,6 +254,8 @@ class NameParser(object):
|
||||
result.score += 1
|
||||
matches.append(result)
|
||||
|
||||
time.sleep(0.05)
|
||||
|
||||
if len(matches):
|
||||
result = max(sorted(matches, reverse=True, key=lambda x: x.which_regex), key=lambda x: x.score)
|
||||
|
||||
|
@ -64,7 +64,7 @@ class CheckVersion():
|
||||
if sickbeard.versionCheckScheduler.action.update():
|
||||
logger.log(u"Update was successful!")
|
||||
ui.notifications.message('Update was successful')
|
||||
threading.Timer(2, sickbeard.invoke_restart, [False]).start()
|
||||
sickbeard.events.put(sickbeard.events.SystemEvent.RESTART)
|
||||
|
||||
def find_install_type(self):
|
||||
"""
|
||||
|
@ -1524,7 +1524,7 @@ class CMD_SickBeardRestart(ApiCall):
|
||||
|
||||
def run(self):
|
||||
""" restart sickbeard """
|
||||
threading.Timer(2, sickbeard.invoke_restart, [False]).start()
|
||||
sickbeard.events.put(sickbeard.events.SystemEvent.RESTART)
|
||||
return _responds(RESULT_SUCCESS, msg="SickRage is restarting...")
|
||||
|
||||
|
||||
@ -1701,7 +1701,7 @@ class CMD_SickBeardShutdown(ApiCall):
|
||||
|
||||
def run(self):
|
||||
""" shutdown sickbeard """
|
||||
threading.Timer(2, sickbeard.invoke_shutdown).start()
|
||||
sickbeard.events.put(sickbeard.events.SystemEvent.SHUTDOWN)
|
||||
return _responds(RESULT_SUCCESS, msg="SickRage is shutting down...")
|
||||
|
||||
|
||||
|
@ -3434,7 +3434,7 @@ class Home(MainHandler):
|
||||
if str(pid) != str(sickbeard.PID):
|
||||
redirect("/home/")
|
||||
|
||||
threading.Timer(2, sickbeard.invoke_shutdown).start()
|
||||
sickbeard.events.put(sickbeard.events.SystemEvent.SHUTDOWN)
|
||||
|
||||
title = "Shutting down"
|
||||
message = "SickRage is shutting down..."
|
||||
@ -3450,7 +3450,7 @@ class Home(MainHandler):
|
||||
t.submenu = HomeMenu()
|
||||
|
||||
# restart
|
||||
threading.Timer(5, sickbeard.invoke_restart, [False]).start()
|
||||
sickbeard.events.put(sickbeard.events.SystemEvent.RESTART)
|
||||
|
||||
return _munge(t)
|
||||
|
||||
@ -3462,7 +3462,7 @@ class Home(MainHandler):
|
||||
updated = sickbeard.versionCheckScheduler.action.update() # @UndefinedVariable
|
||||
if updated:
|
||||
# do a hard restart
|
||||
threading.Timer(2, sickbeard.invoke_restart, [False]).start()
|
||||
sickbeard.events.put(sickbeard.events.SystemEvent.RESTART)
|
||||
|
||||
t = PageTemplate(headers=self.request.headers, file="restart_bare.tmpl")
|
||||
return _munge(t)
|
||||
|
@ -122,13 +122,6 @@ class SRWebServer(threading.Thread):
|
||||
try:
|
||||
self.io_loop.start()
|
||||
self.io_loop.close(True)
|
||||
|
||||
# stop all tasks
|
||||
sickbeard.halt()
|
||||
|
||||
# save all shows to DB
|
||||
sickbeard.saveAll()
|
||||
|
||||
except ValueError:
|
||||
# Ignore errors like "ValueError: I/O operation on closed kqueue fd". These might be thrown during a reload.
|
||||
pass
|
||||
|
Loading…
Reference in New Issue
Block a user