Fix for failed download issues.

Fix for auto-update improperly restarting.
This commit is contained in:
echel0n 2014-05-13 04:16:32 -07:00
parent 2318e43e89
commit b9310444e5
7 changed files with 153 additions and 144 deletions

View file

@ -96,9 +96,10 @@ def daemonize():
try: try:
pid = os.fork() # @UndefinedVariable - only available in UNIX pid = os.fork() # @UndefinedVariable - only available in UNIX
if pid != 0: if pid != 0:
sys.exit(0) os._exit(0)
except OSError, e: except OSError, e:
raise RuntimeError("1st fork failed: %s [%d]" % (e.strerror, e.errno)) sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
os.setsid() # @UndefinedVariable - only available in UNIX os.setsid() # @UndefinedVariable - only available in UNIX
@ -110,18 +111,33 @@ def daemonize():
try: try:
pid = os.fork() # @UndefinedVariable - only available in UNIX pid = os.fork() # @UndefinedVariable - only available in UNIX
if pid != 0: if pid != 0:
sys.exit(0) os._exit(0)
except OSError, e: except OSError, e:
raise RuntimeError("2nd fork failed: %s [%d]" % (e.strerror, e.errno)) sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
dev_null = file('/dev/null', 'r')
os.dup2(dev_null.fileno(), sys.stdin.fileno())
# Write pid
if sickbeard.CREATEPID: if sickbeard.CREATEPID:
pid = str(os.getpid()) pid = str(os.getpid())
logger.log(u"Writing PID " + pid + " to " + str(sickbeard.PIDFILE)) logger.log(u"Writing PID: " + pid + " to " + str(sickbeard.PIDFILE))
file(sickbeard.PIDFILE, 'w').write("%s\n" % pid) try:
file(sickbeard.PIDFILE, 'w').write("%s\n" % pid)
except IOError, e:
logger.log_error_and_exit(
u"Unable to write PID file: " + sickbeard.PIDFILE + " Error: " + str(e.strerror) + " [" + str(
e.errno) + "]")
# Redirect all output
sys.stdout.flush()
sys.stderr.flush()
devnull = getattr(os, 'devnull', '/dev/null')
stdin = file(devnull, 'r')
stdout = file(devnull, 'a+')
stderr = file(devnull, 'a+')
os.dup2(stdin.fileno(), sys.stdin.fileno())
os.dup2(stdout.fileno(), sys.stdout.fileno())
os.dup2(stderr.fileno(), sys.stderr.fileno())
def main(): def main():
""" """
@ -134,8 +150,8 @@ def main():
sickbeard.PROG_DIR = os.path.dirname(sickbeard.MY_FULLNAME) sickbeard.PROG_DIR = os.path.dirname(sickbeard.MY_FULLNAME)
sickbeard.DATA_DIR = sickbeard.PROG_DIR sickbeard.DATA_DIR = sickbeard.PROG_DIR
sickbeard.MY_ARGS = sys.argv[1:] sickbeard.MY_ARGS = sys.argv[1:]
sickbeard.CREATEPID = False
sickbeard.DAEMON = False sickbeard.DAEMON = False
sickbeard.CREATEPID = False
sickbeard.SYS_ENCODING = None sickbeard.SYS_ENCODING = None
@ -196,13 +212,15 @@ def main():
if o in ('-p', '--port'): if o in ('-p', '--port'):
forcedPort = int(a) forcedPort = int(a)
# Run as a daemon # Run as a double forked daemon
if o in ('-d', '--daemon'): if o in ('-d', '--daemon'):
sickbeard.DAEMON = True
# When running as daemon disable consoleLogging and don't start browser
consoleLogging = False
noLaunch = True
if sys.platform == 'win32': if sys.platform == 'win32':
print "Daemonize not supported under Windows, starting normally" sickbeard.DAEMON = False
else:
consoleLogging = False
sickbeard.DAEMON = True
# Specify folder to load the config file from # Specify folder to load the config file from
if o in ('--config',): if o in ('--config',):
@ -214,21 +232,27 @@ def main():
# Write a pidfile if requested # Write a pidfile if requested
if o in ('--pidfile',): if o in ('--pidfile',):
sickbeard.CREATEPID = True
sickbeard.PIDFILE = str(a) sickbeard.PIDFILE = str(a)
# If the pidfile already exists, sickbeard may still be running, so exit # If the pidfile already exists, sickbeard may still be running, so exit
if os.path.exists(sickbeard.PIDFILE): if os.path.exists(sickbeard.PIDFILE):
sys.exit("PID file '" + sickbeard.PIDFILE + "' already exists. Exiting.") sys.exit("PID file: " + sickbeard.PIDFILE + " already exists. Exiting.")
# The pidfile is only useful in daemon mode, make sure we can write the file properly # The pidfile is only useful in daemon mode, make sure we can write the file properly
if sickbeard.DAEMON: if sickbeard.CREATEPID:
sickbeard.CREATEPID = True if sickbeard.DAEMON:
try: pid_dir = os.path.dirname(sickbeard.PIDFILE)
file(sickbeard.PIDFILE, 'w').write("pid\n") if not os.access(pid_dir, os.F_OK):
except IOError, e: sys.exit("PID dir: " + pid_dir + " doesn't exist. Exiting.")
raise SystemExit("Unable to write PID file: %s [%d]" % (e.strerror, e.errno)) if not os.access(pid_dir, os.W_OK):
else: sys.exit("PID dir: " + pid_dir + " must be writable (write permissions). Exiting.")
logger.log(u"Not running in daemon mode. PID file creation disabled.")
else:
if consoleLogging:
sys.stdout.write("Not running in daemon mode. PID file creation disabled.\n")
sickbeard.CREATEPID = False
# If they don't specify a config file then put it in the data dir # If they don't specify a config file then put it in the data dir
if not sickbeard.CONFIG_FILE: if not sickbeard.CONFIG_FILE:
@ -263,16 +287,16 @@ def main():
sickbeard.CFG = ConfigObj(sickbeard.CONFIG_FILE) sickbeard.CFG = ConfigObj(sickbeard.CONFIG_FILE)
CUR_DB_VERSION = db.DBConnection().checkDBVersion() CUR_DB_VERSION = db.DBConnection().checkDBVersion()
if CUR_DB_VERSION > 0: if CUR_DB_VERSION > 0:
if CUR_DB_VERSION < MIN_DB_VERSION: if CUR_DB_VERSION < MIN_DB_VERSION:
raise SystemExit("Your database version (" + str(db.DBConnection().checkDBVersion()) + ") is too old to migrate from with this version of Sick Beard (" + str(MIN_DB_VERSION) + ").\n" + \ raise SystemExit("Your database version (" + str(db.DBConnection().checkDBVersion()) + ") is too old to migrate from with this version of Sick Beard (" + str(MIN_DB_VERSION) + ").\n" + \
"Upgrade using a previous version of SB first, or start with no database file to begin fresh.") "Upgrade using a previous version of SB first, or start with no database file to begin fresh.")
if CUR_DB_VERSION > MAX_DB_VERSION: if CUR_DB_VERSION > MAX_DB_VERSION:
raise SystemExit("Your database version (" + str(db.DBConnection().checkDBVersion()) + ") has been incremented past what this version of Sick Beard supports (" + str(MAX_DB_VERSION) + ").\n" + \ raise SystemExit("Your database version (" + str(db.DBConnection().checkDBVersion()) + ") has been incremented past what this version of Sick Beard supports (" + str(MAX_DB_VERSION) + ").\n" + \
"If you have used other forks of SB, your database may be unusable due to their modifications.") "If you have used other forks of SB, your database may be unusable due to their modifications.")
# Initialize the config and our threads # Initialize the config and our threads
sickbeard.initialize(consoleLogging=consoleLogging) sickbeard.initialize(consoleLogging=consoleLogging)
sickbeard.showList = [] sickbeard.showList = []
@ -306,17 +330,17 @@ def main():
try: try:
initWebServer({ initWebServer({
'port': startPort, 'port': startPort,
'host': webhost, 'host': webhost,
'data_root': os.path.join(sickbeard.PROG_DIR, 'gui/'+sickbeard.GUI_NAME), 'data_root': os.path.join(sickbeard.PROG_DIR, 'gui/'+sickbeard.GUI_NAME),
'web_root': sickbeard.WEB_ROOT, 'web_root': sickbeard.WEB_ROOT,
'log_dir': log_dir, 'log_dir': log_dir,
'username': sickbeard.WEB_USERNAME, 'username': sickbeard.WEB_USERNAME,
'password': sickbeard.WEB_PASSWORD, 'password': sickbeard.WEB_PASSWORD,
'enable_https': sickbeard.ENABLE_HTTPS, 'enable_https': sickbeard.ENABLE_HTTPS,
'https_cert': sickbeard.HTTPS_CERT, 'https_cert': sickbeard.HTTPS_CERT,
'https_key': sickbeard.HTTPS_KEY, 'https_key': sickbeard.HTTPS_KEY,
}) })
except IOError: except IOError:
logger.log(u"Unable to start web server, is something else running on port %d?" % startPort, logger.ERROR) logger.log(u"Unable to start web server, is something else running on port %d?" % startPort, logger.ERROR)
if sickbeard.LAUNCH_BROWSER and not sickbeard.DAEMON: if sickbeard.LAUNCH_BROWSER and not sickbeard.DAEMON:
@ -341,12 +365,13 @@ def main():
# Stay alive while my threads do the work # Stay alive while my threads do the work
while (True): while (True):
time.sleep(1)
if sickbeard.invoked_command: if sickbeard.invoked_command:
sickbeard.invoked_command() sickbeard.invoked_command()
sickbeard.invoked_command = None sickbeard.invoked_command = None
time.sleep(1)
return return
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -1259,12 +1259,21 @@ def halt():
__INITIALIZED__ = False __INITIALIZED__ = False
def remove_pid_file(PIDFILE):
try:
if os.path.exists(PIDFILE):
os.remove(PIDFILE)
except (IOError, OSError):
return False
return True
def sig_handler(signum=None, frame=None): def sig_handler(signum=None, frame=None):
if type(signum) != type(None): if type(signum) != type(None):
logger.log(u"Signal %i caught, saving and exiting..." % int(signum)) logger.log(u"Signal %i caught, saving and exiting..." % int(signum))
saveAndShutdown() saveAndShutdown()
def saveAll(): def saveAll():
global showList global showList
@ -1288,7 +1297,7 @@ def saveAndShutdown(restart=False):
if CREATEPID: if CREATEPID:
logger.log(u"Removing pidfile " + str(PIDFILE)) logger.log(u"Removing pidfile " + str(PIDFILE))
os.remove(PIDFILE) remove_pid_file(PIDFILE)
if restart: if restart:
install_type = versionCheckScheduler.action.install_type install_type = versionCheckScheduler.action.install_type
@ -1310,7 +1319,7 @@ def saveAndShutdown(restart=False):
popen_list += MY_ARGS popen_list += MY_ARGS
if '--nolaunch' not in popen_list: if '--nolaunch' not in popen_list:
popen_list += ['--nolaunch'] popen_list += ['--nolaunch']
logger.log(u"Restarting Sick Beard with " + str(popen_list)) logger.log(u"Restarting SickRage with " + str(popen_list))
logger.close() logger.close()
subprocess.Popen(popen_list, cwd=os.getcwd()) subprocess.Popen(popen_list, cwd=os.getcwd())

View file

@ -22,17 +22,12 @@ import datetime
from sickbeard import db from sickbeard import db
from sickbeard import logger from sickbeard import logger
from sickbeard import exceptions from sickbeard.exceptions import ex, EpisodeNotFoundException
from sickbeard.history import dateFormat from sickbeard.history import dateFormat
from sickbeard.common import Quality from sickbeard.common import Quality
from sickbeard.common import WANTED, FAILED from sickbeard.common import WANTED, FAILED
def _log_helper(message, level=logger.MESSAGE):
logger.log(message, level)
return message + u"\n"
def prepareFailedName(release): def prepareFailedName(release):
"""Standardizes release name for failed DB""" """Standardizes release name for failed DB"""
@ -41,6 +36,10 @@ def prepareFailedName(release):
fixed = fixed.rpartition(".")[0] fixed = fixed.rpartition(".")[0]
fixed = re.sub("[\.\-\+\ ]", "_", fixed) fixed = re.sub("[\.\-\+\ ]", "_", fixed)
if not isinstance(fixed, unicode):
fixed = unicode(fixed, 'utf-8')
return fixed return fixed
@ -55,26 +54,26 @@ def logFailed(release):
sql_results = myDB.select("SELECT * FROM history WHERE release=?", [release]) sql_results = myDB.select("SELECT * FROM history WHERE release=?", [release])
if len(sql_results) == 0: if len(sql_results) == 0:
log_str += _log_helper( logger.log(
u"Release not found in snatch history. Recording it as bad with no size and no proivder.", logger.WARNING) u"Release not found in snatch history. Recording it as bad with no size and no proivder.", logger.WARNING)
log_str += _log_helper( logger.log(
u"Future releases of the same name from providers that don't return size will be skipped.", logger.WARNING) u"Future releases of the same name from providers that don't return size will be skipped.", logger.WARNING)
elif len(sql_results) > 1: elif len(sql_results) > 1:
log_str += _log_helper(u"Multiple logged snatches found for release", logger.WARNING) logger.log(u"Multiple logged snatches found for release", logger.WARNING)
sizes = len(set(x["size"] for x in sql_results)) sizes = len(set(x["size"] for x in sql_results))
providers = len(set(x["provider"] for x in sql_results)) providers = len(set(x["provider"] for x in sql_results))
if sizes == 1: if sizes == 1:
log_str += _log_helper(u"However, they're all the same size. Continuing with found size.", logger.WARNING) logger.log(u"However, they're all the same size. Continuing with found size.", logger.WARNING)
size = sql_results[0]["size"] size = sql_results[0]["size"]
else: else:
log_str += _log_helper( logger.log(
u"They also vary in size. Deleting the logged snatches and recording this release with no size/provider", u"They also vary in size. Deleting the logged snatches and recording this release with no size/provider",
logger.WARNING) logger.WARNING)
for result in sql_results: for result in sql_results:
deleteLoggedSnatch(result["release"], result["size"], result["provider"]) deleteLoggedSnatch(result["release"], result["size"], result["provider"])
if providers == 1: if providers == 1:
log_str += _log_helper(u"They're also from the same provider. Using it as well.") logger.log(u"They're also from the same provider. Using it as well.")
provider = sql_results[0]["provider"] provider = sql_results[0]["provider"]
else: else:
size = sql_results[0]["size"] size = sql_results[0]["size"]
@ -113,74 +112,45 @@ def hasFailed(release, size, provider="%"):
return (len(sql_results) > 0) return (len(sql_results) > 0)
def revertEpisode(show_obj, season, episode=None): def revertEpisode(epObj):
"""Restore the episodes of a failed download to their original state""" """Restore the episodes of a failed download to their original state"""
myDB = db.DBConnection("failed.db") myDB = db.DBConnection("failed.db")
log_str = u""
sql_results = myDB.select("SELECT * FROM history WHERE showid=? AND season=?", [show_obj.indexerid, season]) sql_results = myDB.select("SELECT * FROM history WHERE showid=? AND season=?", [epObj.show.indexerid, epObj.season])
# {episode: result, ...}
history_eps = dict([(res["episode"], res) for res in sql_results]) history_eps = dict([(res["episode"], res) for res in sql_results])
if episode: try:
try: logger.log(u"Reverting episode (%s, %s): %s" % (epObj.season, epObj.episode, epObj.name))
ep_obj = show_obj.getEpisode(season, episode) with epObj.lock:
log_str += _log_helper(u"Reverting episode (%s, %s): %s" % (season, episode, ep_obj.name)) if epObj.episode in history_eps:
with ep_obj.lock: logger.log(u"Found in history")
if episode in history_eps: epObj.status = history_eps[epObj.episode]['old_status']
log_str += _log_helper(u"Found in history") else:
ep_obj.status = history_eps[episode]['old_status'] logger.log(u"WARNING: Episode not found in history. Setting it back to WANTED",
else: logger.WARNING)
log_str += _log_helper(u"WARNING: Episode not found in history. Setting it back to WANTED", epObj.status = WANTED
logger.WARNING)
ep_obj.status = WANTED
ep_obj.saveToDB() epObj.saveToDB()
except exceptions.EpisodeNotFoundException, e: except EpisodeNotFoundException, e:
log_str += _log_helper(u"Unable to create episode, please set its status manually: " + exceptions.ex(e), logger.log(u"Unable to create episode, please set its status manually: " + ex(e),
logger.WARNING) logger.WARNING)
else:
# Whole season return
log_str += _log_helper(u"Setting season to wanted: " + str(season))
for ep_obj in show_obj.getAllEpisodes(season):
log_str += _log_helper(u"Reverting episode (%d, %d): %s" % (season, ep_obj.episode, ep_obj.name))
with ep_obj.lock:
if ep_obj in history_eps:
log_str += _log_helper(u"Found in history")
ep_obj.status = history_eps[ep_obj]['old_status']
else:
log_str += _log_helper(u"WARNING: Episode not found in history. Setting it back to WANTED",
logger.WARNING)
ep_obj.status = WANTED
ep_obj.saveToDB()
return log_str
def markFailed(show_obj, season, episode=None): def markFailed(epObj):
log_str = u"" log_str = u""
if episode: try:
try: with epObj.lock:
ep_obj = show_obj.getEpisode(season, episode) quality = Quality.splitCompositeStatus(epObj.status)[1]
epObj.status = Quality.compositeStatus(FAILED, quality)
epObj.saveToDB()
with ep_obj.lock: except EpisodeNotFoundException, e:
quality = Quality.splitCompositeStatus(ep_obj.status)[1] logger.log(u"Unable to get episode, please set its status manually: " + ex(e), logger.WARNING)
ep_obj.status = Quality.compositeStatus(FAILED, quality)
ep_obj.saveToDB()
except exceptions.EpisodeNotFoundException, e:
log_str += _log_helper(u"Unable to get episode, please set its status manually: " + exceptions.ex(e),
logger.WARNING)
else:
# Whole season
for ep_obj in show_obj.getAllEpisodes(season):
with ep_obj.lock:
quality = Quality.splitCompositeStatus(ep_obj.status)[1]
ep_obj.status = Quality.compositeStatus(FAILED, quality)
ep_obj.saveToDB()
return log_str return log_str
@ -191,6 +161,7 @@ def logSnatch(searchResult):
logDate = datetime.datetime.today().strftime(dateFormat) logDate = datetime.datetime.today().strftime(dateFormat)
release = prepareFailedName(searchResult.name) release = prepareFailedName(searchResult.name)
providerClass = searchResult.provider providerClass = searchResult.provider
if providerClass is not None: if providerClass is not None:
provider = providerClass.name provider = providerClass.name
@ -200,13 +171,11 @@ def logSnatch(searchResult):
show_obj = searchResult.episodes[0].show show_obj = searchResult.episodes[0].show
for episode in searchResult.episodes: for episode in searchResult.episodes:
old_status = show_obj.getEpisode(episode.season, episode.episode).status
myDB.action( myDB.action(
"INSERT INTO history (date, size, release, provider, showid, season, episode, old_status)" "INSERT INTO history (date, size, release, provider, showid, season, episode, old_status)"
"VALUES (?, ?, ?, ?, ?, ?, ?, ?)", "VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
[logDate, searchResult.size, release, provider, show_obj.indexerid, episode.season, episode.episode, [logDate, searchResult.size, release, provider, show_obj.indexerid, episode.season, episode.episode,
old_status]) episode.status])
def deleteLoggedSnatch(release, size, provider): def deleteLoggedSnatch(release, size, provider):
@ -224,13 +193,11 @@ def trimHistory():
(datetime.datetime.today() - datetime.timedelta(days=30)).strftime(dateFormat))) (datetime.datetime.today() - datetime.timedelta(days=30)).strftime(dateFormat)))
def findRelease(show, season, episode): def findRelease(epObj):
""" """
Find releases in history by show ID and season. Find releases in history by show ID and season.
Return None for release if multiple found or no release found. Return None for release if multiple found or no release found.
""" """
if not show: return (None, None, None)
if not season: return (None, None, None)
release = None release = None
provider = None provider = None
@ -238,13 +205,13 @@ def findRelease(show, season, episode):
myDB = db.DBConnection("failed.db") myDB = db.DBConnection("failed.db")
# Clear old snatches for this release if any exist # Clear old snatches for this release if any exist
myDB.action("DELETE FROM history WHERE showid=" + str(show.indexerid) + " AND season=" + str( myDB.action("DELETE FROM history WHERE showid=" + str(epObj.show.indexerid) + " AND season=" + str(
season) + " AND episode=" + str(episode) + " AND date < (SELECT max(date) FROM history WHERE showid=" + str( epObj.season) + " AND episode=" + str(epObj.episode) + " AND date < (SELECT max(date) FROM history WHERE showid=" + str(
show.indexerid) + " AND season=" + str(season) + " AND episode=" + str(episode) + ")") epObj.show.indexerid) + " AND season=" + str(epObj.season) + " AND episode=" + str(epObj.episode) + ")")
# Search for release in snatch history # Search for release in snatch history
results = myDB.select("SELECT release, provider, date FROM history WHERE showid=? AND season=? AND episode=?", results = myDB.select("SELECT release, provider, date FROM history WHERE showid=? AND season=? AND episode=?",
[show.indexerid, season, episode]) [epObj.show.indexerid, epObj.season, epObj.episode])
for result in results: for result in results:
release = str(result["release"]) release = str(result["release"])
@ -255,9 +222,9 @@ def findRelease(show, season, episode):
myDB.action("DELETE FROM history WHERE release=? AND date!=?", [release, date]) myDB.action("DELETE FROM history WHERE release=? AND date!=?", [release, date])
# Found a previously failed release # Found a previously failed release
logger.log(u"Failed release found for season (%s): (%s)" % (season, result["release"]), logger.DEBUG) logger.log(u"Failed release found for season (%s): (%s)" % (epObj.season, result["release"]), logger.DEBUG)
return (release, provider) return (release, provider)
# Release was not found # Release was not found
logger.log(u"No releases found for season (%s) of (%s)" % (season, show.indexerid), logger.DEBUG) logger.log(u"No releases found for season (%s) of (%s)" % (epObj.season, epObj.show.indexerid), logger.DEBUG)
return (release, provider) return (release, provider)

View file

@ -85,11 +85,11 @@ def logSubtitle(showid, season, episode, status, subtitleResult):
_logHistoryItem(action, showid, season, episode, quality, resource, provider) _logHistoryItem(action, showid, season, episode, quality, resource, provider)
def logFailed(indexerid, season, episode, status, release, provider=None): def logFailed(epObj, release, provider=None):
showid = int(indexerid) showid = int(epObj.show.indexerid)
season = int(season) season = int(epObj.season)
epNum = int(episode) epNum = int(epObj.episode)
status, quality = Quality.splitCompositeStatus(status) status, quality = Quality.splitCompositeStatus(epObj.status)
action = Quality.compositeStatus(FAILED, quality) action = Quality.compositeStatus(FAILED, quality)
_logHistoryItem(action, showid, season, epNum, quality, release, provider) _logHistoryItem(action, showid, season, epNum, quality, release, provider)

View file

@ -625,7 +625,6 @@ class PostProcessor(object):
# detect and convert scene numbered releases # detect and convert scene numbered releases
season, cur_episode = sickbeard.scene_numbering.get_indexer_numbering(indexer_id,indexer,season,cur_episode) season, cur_episode = sickbeard.scene_numbering.get_indexer_numbering(indexer_id,indexer,season,cur_episode)
self._log(u"Episode object has been scene converted to " + str(season) + "x" + str(cur_episode), logger.DEBUG)
# now that we've figured out which episode this file is just load it manually # now that we've figured out which episode this file is just load it manually
try: try:
@ -634,6 +633,9 @@ class PostProcessor(object):
self._log(u"Unable to create episode: " + ex(e), logger.DEBUG) self._log(u"Unable to create episode: " + ex(e), logger.DEBUG)
raise exceptions.PostProcessingFailed() raise exceptions.PostProcessingFailed()
self._log(u"Episode object has been converted from Scene numbering " + str(curEp.scene_season) + "x" + str(
curEp.scene_episode) + " to Indexer numbering" + str(curEp.season) + "x" + str(curEp.episode))
# associate all the episodes together under a single root episode # associate all the episodes together under a single root episode
if root_ep == None: if root_ep == None:
root_ep = curEp root_ep = curEp

View file

@ -257,21 +257,22 @@ class FailedQueueItem(generic_queue.QueueItem):
def execute(self): def execute(self):
generic_queue.QueueItem.execute(self) generic_queue.QueueItem.execute(self)
failed_episodes = []
for i, epObj in enumerate(self.episodes): for i, epObj in enumerate(self.episodes):
(release, provider) = failed_history.findRelease(self.show, epObj.season, epObj.episode) (release, provider) = failed_history.findRelease(epObj)
if release: if release:
logger.log(u"Marking release as bad: " + release) logger.log(u"Marking release as bad: " + release)
failed_history.markFailed(self.show, epObj.season, epObj.episode) failed_history.markFailed(epObj)
failed_history.logFailed(release) failed_history.logFailed(release)
history.logFailed(self.show.indexerid, epObj.season, epObj.episode, epObj.status, release, provider) history.logFailed(epObj, release, provider)
failed_history.revertEpisode(epObj)
failed_history.revertEpisode(self.show, epObj.season, epObj.episode) failed_episodes.append(epObj)
try: try:
logger.log( logger.log(
"Beginning failed download search for episodes from Season [" + str(self.episodes[0].season) + "]") "Beginning failed download search for episodes from Season [" + str(self.episodes[0].season) + "]")
searchResult = search.searchProviders(self, self.show, self.episodes[0].season, self.episodes, False, True) searchResult = search.searchProviders(self, self.show, failed_episodes[0].season, failed_episodes, False, True)
if searchResult: if searchResult:
self.success = SearchQueue().snatch_item(searchResult) self.success = SearchQueue().snatch_item(searchResult)

View file

@ -27,6 +27,7 @@ import tarfile
import stat import stat
import traceback import traceback
import gh_api as github import gh_api as github
import threading
import sickbeard import sickbeard
from sickbeard import helpers from sickbeard import helpers
@ -57,23 +58,27 @@ class CheckVersion():
self.updater = None self.updater = None
def run(self): def run(self):
updated = None
if self.check_for_new_version(): if self.check_for_new_version():
if sickbeard.AUTO_UPDATE: if sickbeard.AUTO_UPDATE:
logger.log(u"New update found for SickRage, starting auto-updater ...") logger.log(u"New update found for SickRage, starting auto-updater ...")
updated = sickbeard.versionCheckScheduler.action.update() updated = sickbeard.versionCheckScheduler.action.update()
if updated: if updated:
logger.log(u"Update was successfull, restarting SickRage ...") logger.log(u"Update was successfull, restarting SickRage ...")
sickbeard.restart(False)
# refresh scene exceptions too # do a soft restart
scene_exceptions.retrieve_exceptions() threading.Timer(2, sickbeard.invoke_restart, [False]).start()
# refresh network timezones if not updated:
network_timezones.update_network_dict() # refresh scene exceptions too
scene_exceptions.retrieve_exceptions()
# sure, why not? # refresh network timezones
if sickbeard.USE_FAILED_DOWNLOADS: network_timezones.update_network_dict()
failed_history.trimHistory()
# sure, why not?
if sickbeard.USE_FAILED_DOWNLOADS:
failed_history.trimHistory()
def find_install_type(self): def find_install_type(self):
""" """