diff --git a/gui/slick/interfaces/default/inc_bottom.tmpl b/gui/slick/interfaces/default/inc_bottom.tmpl
index 2ef35410..fd44b668 100644
--- a/gui/slick/interfaces/default/inc_bottom.tmpl
+++ b/gui/slick/interfaces/default/inc_bottom.tmpl
@@ -13,9 +13,7 @@
#set $numGoodShows = len([x for x in $sickbeard.showList if x.paused == 0 and x.status != "Ended"])
#set $numDLEpisodes = $myDB.select("SELECT COUNT(*) FROM tv_episodes WHERE status IN ("+",".join([str(x) for x in $Quality.DOWNLOADED + [$ARCHIVED]])+") AND season != 0 and episode != 0 AND airdate <= "+$today+"")[0][0]
#set $numEpisodes = $myDB.select("SELECT COUNT(*) FROM tv_episodes WHERE season != 0 and episode != 0 AND (airdate != 1 OR status IN ("+",".join([str(x) for x in ($Quality.DOWNLOADED + $Quality.SNATCHED + $Quality.SNATCHED_PROPER) + [$ARCHIVED]])+")) AND airdate <= "+$today+" AND status != "+str($IGNORED)+"")[0][0]
-$numShows shows ($numGoodShows active) | $numDLEpisodes/$numEpisodes episodes downloaded |
-Search: <%=str(sickbeard.currentSearchScheduler.timeLeft()).split('.')[0]%> |
-
+$numShows shows ($numGoodShows active) | $numDLEpisodes/$numEpisodes episodes downloaded |
Backlog: $sbdatetime.sbdatetime.sbfdate($sickbeard.backlogSearchScheduler.nextRun())
diff --git a/lib/concurrent/futures/thread.py b/lib/concurrent/futures/thread.py
index f4676e13..9d435cd0 100644
--- a/lib/concurrent/futures/thread.py
+++ b/lib/concurrent/futures/thread.py
@@ -86,7 +86,7 @@ def _worker(executor_reference, work_queue):
_base.LOGGER.critical('Exception in worker', exc_info=True)
class ThreadPoolExecutor(_base.Executor):
- def __init__(self, max_workers, name=None):
+ def __init__(self, max_workers):
"""Initializes a new ThreadPoolExecutor instance.
Args:
@@ -98,7 +98,6 @@ class ThreadPoolExecutor(_base.Executor):
self._threads = set()
self._shutdown = False
self._shutdown_lock = threading.Lock()
- self._name = name
def submit(self, fn, *args, **kwargs):
with self._shutdown_lock:
@@ -109,11 +108,16 @@ class ThreadPoolExecutor(_base.Executor):
w = _WorkItem(f, fn, args, kwargs)
self._work_queue.put(w)
- self._adjust_thread_count()
+
+ name = None
+ if kwargs.has_key('name'):
+ name = kwargs.pop('name')
+
+ self._adjust_thread_count(name)
return f
submit.__doc__ = _base.Executor.submit.__doc__
- def _adjust_thread_count(self):
+ def _adjust_thread_count(self, name=None):
# When the executor gets lost, the weakref callback will wake up
# the worker threads.
def weakref_cb(_, q=self._work_queue):
@@ -124,8 +128,8 @@ class ThreadPoolExecutor(_base.Executor):
t = threading.Thread(target=_worker,
args=(weakref.ref(self, weakref_cb),
self._work_queue),)
- if self._name:
- t.name = self._name
+ if name:
+ t.name = name
t.daemon = True
t.start()
self._threads.add(t)
diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py
index 146566ff..495ab97d 100644
--- a/sickbeard/__init__.py
+++ b/sickbeard/__init__.py
@@ -33,7 +33,7 @@ from sickbeard import providers, metadata, config
from providers import ezrss, tvtorrents, btn, newznab, womble, thepiratebay, torrentleech, kat, publichd, iptorrents, \
omgwtfnzbs, scc, hdtorrents, torrentday, hdbits, nextgen, speedcd
from sickbeard.config import CheckSection, check_setting_int, check_setting_str, ConfigMigrator, naming_ep_type
-from sickbeard import searchCurrent, searchBacklog, showUpdater, versionChecker, properFinder, autoPostProcesser, \
+from sickbeard import searchBacklog, showUpdater, versionChecker, properFinder, autoPostProcesser, \
subtitles, traktWatchListChecker
from sickbeard import helpers, db, exceptions, show_queue, search_queue, scheduler, show_name_helpers
from sickbeard import logger
@@ -74,7 +74,6 @@ PIDFILE = ''
DAEMON = None
backlogSearchScheduler = None
-currentSearchScheduler = None
showUpdateScheduler = None
versionCheckScheduler = None
showQueueScheduler = None
@@ -474,7 +473,7 @@ def initialize(consoleLogging=True):
global ACTUAL_LOG_DIR, LOG_DIR, WEB_PORT, WEB_LOG, ENCRYPTION_VERSION, WEB_ROOT, WEB_USERNAME, WEB_PASSWORD, WEB_HOST, WEB_IPV6, USE_API, API_KEY, ENABLE_HTTPS, HTTPS_CERT, HTTPS_KEY, \
HANDLE_REVERSE_PROXY, USE_NZBS, USE_TORRENTS, NZB_METHOD, NZB_DIR, DOWNLOAD_PROPERS, PREFER_EPISODE_RELEASES, ALLOW_HIGH_PRIORITY, TORRENT_METHOD, \
SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, SAB_HOST, \
- NZBGET_USERNAME, NZBGET_PASSWORD, NZBGET_CATEGORY, NZBGET_HOST, NZBGET_USE_HTTPS, currentSearchScheduler, backlogSearchScheduler, \
+ NZBGET_USERNAME, NZBGET_PASSWORD, NZBGET_CATEGORY, NZBGET_HOST, NZBGET_USE_HTTPS, backlogSearchScheduler, \
TORRENT_USERNAME, TORRENT_PASSWORD, TORRENT_HOST, TORRENT_PATH, TORRENT_RATIO, TORRENT_SEED_TIME, TORRENT_PAUSED, TORRENT_HIGH_BANDWIDTH, TORRENT_LABEL, \
USE_XBMC, XBMC_ALWAYS_ON, XBMC_NOTIFY_ONSNATCH, XBMC_NOTIFY_ONDOWNLOAD, XBMC_NOTIFY_ONSUBTITLEDOWNLOAD, XBMC_UPDATE_FULL, XBMC_UPDATE_ONLYFIRST, \
XBMC_UPDATE_LIBRARY, XBMC_HOST, XBMC_USERNAME, XBMC_PASSWORD, \
@@ -1018,12 +1017,6 @@ def initialize(consoleLogging=True):
newznabProviderList = providers.getNewznabProviderList(NEWZNAB_DATA)
providerList = providers.makeProviderList()
- # initialize newznab providers
- currentSearchScheduler = scheduler.Scheduler(searchCurrent.CurrentSearcher(),
- cycleTime=datetime.timedelta(minutes=SEARCH_FREQUENCY),
- threadName="SEARCH",
- runImmediately=True)
-
# the interval for this is stored inside the ShowUpdater class
showUpdaterInstance = showUpdater.ShowUpdater()
showUpdateScheduler = scheduler.Scheduler(showUpdaterInstance,
@@ -1039,7 +1032,8 @@ def initialize(consoleLogging=True):
showQueueScheduler = scheduler.Scheduler(show_queue.ShowQueue(),
cycleTime=datetime.timedelta(seconds=3),
threadName="SHOWQUEUE",
- silent=True)
+ silent=True,
+ runImmediately=True)
searchQueueScheduler = scheduler.Scheduler(search_queue.SearchQueue(),
cycleTime=datetime.timedelta(seconds=3),
@@ -1094,7 +1088,7 @@ def initialize(consoleLogging=True):
def start():
- global __INITIALIZED__, currentSearchScheduler, backlogSearchScheduler, \
+ global __INITIALIZED__, backlogSearchScheduler, \
showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \
properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \
subtitlesFinderScheduler, started, USE_SUBTITLES, \
@@ -1104,8 +1098,11 @@ def start():
if __INITIALIZED__:
- # start the search scheduler
- currentSearchScheduler.thread.start()
+ # start the queue checker
+ showQueueScheduler.thread.start()
+
+ # start the version checker
+ versionCheckScheduler.thread.start()
# start the backlog scheduler
backlogSearchScheduler.thread.start()
@@ -1113,12 +1110,6 @@ def start():
# start the show updater
showUpdateScheduler.thread.start()
- # start the version checker
- versionCheckScheduler.thread.start()
-
- # start the queue checker
- showQueueScheduler.thread.start()
-
# start the search queue checker
searchQueueScheduler.thread.start()
@@ -1139,7 +1130,7 @@ def start():
def halt():
- global __INITIALIZED__, currentSearchScheduler, backlogSearchScheduler, showUpdateScheduler, \
+ global __INITIALIZED__, backlogSearchScheduler, showUpdateScheduler, \
showQueueScheduler, properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \
subtitlesFinderScheduler, started, \
traktWatchListCheckerSchedular
@@ -1152,13 +1143,6 @@ def halt():
# abort all the threads
- currentSearchScheduler.abort = True
- logger.log(u"Waiting for the SEARCH thread to exit")
- try:
- currentSearchScheduler.thread.join(10)
- except:
- pass
-
backlogSearchScheduler.abort = True
logger.log(u"Waiting for the BACKLOG thread to exit")
try:
diff --git a/sickbeard/config.py b/sickbeard/config.py
index 01c08cfb..c4b5a6e9 100644
--- a/sickbeard/config.py
+++ b/sickbeard/config.py
@@ -163,7 +163,6 @@ def change_SEARCH_FREQUENCY(freq):
if sickbeard.SEARCH_FREQUENCY < sickbeard.MIN_SEARCH_FREQUENCY:
sickbeard.SEARCH_FREQUENCY = sickbeard.MIN_SEARCH_FREQUENCY
- sickbeard.currentSearchScheduler.cycleTime = datetime.timedelta(minutes=sickbeard.SEARCH_FREQUENCY)
sickbeard.backlogSearchScheduler.cycleTime = datetime.timedelta(minutes=sickbeard.get_backlog_cycle_time())
def change_UPDATE_FREQUENCY(freq):
diff --git a/sickbeard/db.py b/sickbeard/db.py
index c48829c1..cbe67063 100644
--- a/sickbeard/db.py
+++ b/sickbeard/db.py
@@ -57,6 +57,8 @@ class DBConnection:
self.connection.row_factory = sqlite3.Row
def checkDBVersion(self):
+ result = None
+
try:
result = self.select("SELECT db_version FROM db_version")
except sqlite3.OperationalError, e:
diff --git a/sickbeard/generic_queue.py b/sickbeard/generic_queue.py
index 4fb2c59f..8257c245 100644
--- a/sickbeard/generic_queue.py
+++ b/sickbeard/generic_queue.py
@@ -20,8 +20,12 @@ import datetime
import threading
import Queue
+import sickbeard
+from lib.concurrent.futures.thread import ThreadPoolExecutor
+
from sickbeard import logger
+
class QueuePriorities:
LOW = 10
NORMAL = 20
@@ -29,11 +33,12 @@ class QueuePriorities:
class GenericQueue:
def __init__(self):
+ #self.executor = ThreadPoolExecutor(sickbeard.NUM_OF_THREADS)
self.currentItem = None
self.thread = None
self.queue_name = "QUEUE"
self.min_priority = 0
- self.queue = Queue.PriorityQueue()
+ self.queue = Queue.Queue()
def pause(self):
logger.log(u"Pausing queue")
@@ -45,7 +50,7 @@ class GenericQueue:
def add_item(self, item):
item.added = datetime.datetime.now()
- self.queue.put(item, item.priority)
+ self.queue.put(item)
return item
def run(self, queue=None):
@@ -67,12 +72,10 @@ class GenericQueue:
return
threadName = self.queue_name + '-' + queueItem.get_thread_name()
- self.thread = threading.Thread(None, queueItem.execute, threadName)
- self.thread.start()
-
+ executor = ThreadPoolExecutor(sickbeard.NUM_OF_THREADS)
+ self.thread = executor.submit(queueItem.execute, name=threadName)
self.currentItem = queueItem
-
class QueueItem:
def __init__(self, name, action_id=0):
self.name = name
diff --git a/sickbeard/name_parser/parser.py b/sickbeard/name_parser/parser.py
index bb92e1fd..a6b6149e 100644
--- a/sickbeard/name_parser/parser.py
+++ b/sickbeard/name_parser/parser.py
@@ -213,7 +213,6 @@ class NameParser(object):
i = result = 0
for integer, numeral in numeral_map:
while n[i:i + len(numeral)] == numeral:
- time.sleep(1)
result += integer
i += len(numeral)
diff --git a/sickbeard/providers/btn.py b/sickbeard/providers/btn.py
index 4f40ec08..0de0437a 100644
--- a/sickbeard/providers/btn.py
+++ b/sickbeard/providers/btn.py
@@ -326,9 +326,8 @@ class BTNCache(tvcache.TVCache):
if ci is not None:
cl.append(ci)
- if len(cl) > 0:
- myDB = self._getDB()
- myDB.mass_action(cl)
+ myDB = self._getDB()
+ myDB.mass_action(cl)
else:
raise AuthException(
diff --git a/sickbeard/providers/generic.py b/sickbeard/providers/generic.py
index c3ca587f..97e024ec 100644
--- a/sickbeard/providers/generic.py
+++ b/sickbeard/providers/generic.py
@@ -236,12 +236,10 @@ class GenericProvider:
searchItems = {}
itemList = []
- if manualSearch:
+ if not manualSearch:
self.cache.updateCache()
for epObj in episodes:
-
-
cacheResult = self.cache.searchCache(epObj, manualSearch)
if len(cacheResult):
results.update(cacheResult)
diff --git a/sickbeard/providers/hdtorrents.py b/sickbeard/providers/hdtorrents.py
index d46f40a7..d84d5594 100644
--- a/sickbeard/providers/hdtorrents.py
+++ b/sickbeard/providers/hdtorrents.py
@@ -355,9 +355,8 @@ class HDTorrentsCache(tvcache.TVCache):
if ci is not None:
cl.append(ci)
- if len(cl) > 0:
- myDB = self._getDB()
- myDB.mass_action(cl)
+ myDB = self._getDB()
+ myDB.mass_action(cl)
def _parseItem(self, item):
@@ -366,7 +365,7 @@ class HDTorrentsCache(tvcache.TVCache):
if not title or not url:
return None
- logger.log(u"Attempting to cache item:" + title, logger.DEBUG)
+ logger.log(u"Attempting to cache item:[" + title +"]", logger.DEBUG)
return self._addCacheEntry(title, url)
diff --git a/sickbeard/providers/iptorrents.py b/sickbeard/providers/iptorrents.py
index 10b9b665..c791f0b5 100644
--- a/sickbeard/providers/iptorrents.py
+++ b/sickbeard/providers/iptorrents.py
@@ -301,9 +301,8 @@ class IPTorrentsCache(tvcache.TVCache):
if ci is not None:
cl.append(ci)
- if len(cl) > 0:
- myDB = self._getDB()
- myDB.mass_action(cl)
+ myDB = self._getDB()
+ myDB.mass_action(cl)
def _parseItem(self, item):
@@ -312,7 +311,7 @@ class IPTorrentsCache(tvcache.TVCache):
if not title or not url:
return None
- logger.log(u"Attempting to cache item:" + title, logger.DEBUG)
+ logger.log(u"Attempting to cache item:[" + title +"]", logger.DEBUG)
return self._addCacheEntry(title, url)
diff --git a/sickbeard/providers/kat.py b/sickbeard/providers/kat.py
index 2da4b997..4eeb020e 100644
--- a/sickbeard/providers/kat.py
+++ b/sickbeard/providers/kat.py
@@ -424,15 +424,13 @@ class KATCache(tvcache.TVCache):
cl = []
for result in rss_results:
-
item = (result[0], result[1])
ci = self._parseItem(item)
if ci is not None:
cl.append(ci)
- if len(cl) > 0:
- myDB = self._getDB()
- myDB.mass_action(cl)
+ myDB = self._getDB()
+ myDB.mass_action(cl)
def _parseItem(self, item):
@@ -441,7 +439,7 @@ class KATCache(tvcache.TVCache):
if not title or not url:
return None
- logger.log(u"Attempting to cache item:" + title, logger.DEBUG)
+ logger.log(u"Attempting to cache item:[" + title +"]", logger.DEBUG)
return self._addCacheEntry(title, url)
diff --git a/sickbeard/providers/newznab.py b/sickbeard/providers/newznab.py
index d3d27b6a..08854da0 100644
--- a/sickbeard/providers/newznab.py
+++ b/sickbeard/providers/newznab.py
@@ -272,3 +272,59 @@ class NewznabCache(tvcache.TVCache):
def _checkAuth(self, data):
return self.provider._checkAuthFromData(data)
+
+
+ def updateCache(self):
+ if not self.shouldUpdate():
+ return
+
+ if self._checkAuth(None):
+ data = self._getRSSData()
+
+ # as long as the http request worked we count this as an update
+ if data:
+ self.setLastUpdate()
+ else:
+ return []
+
+ # now that we've loaded the current RSS feed lets delete the old cache
+ logger.log(u"Clearing " + self.provider.name + " cache and updating with new information")
+ self._clearCache()
+
+
+ if self._checkAuth(data):
+ items = data.entries
+ ql = []
+ for item in items:
+ ci = self._parseItem(item)
+ if ci is not None:
+ ql.append(ci)
+
+ myDB = self._getDB()
+ myDB.mass_action(ql)
+
+ else:
+ raise AuthException(
+ u"Your authentication credentials for " + self.provider.name + " are incorrect, check your config")
+
+ return []
+
+
+ # overwrite method with that parses the rageid from the newznab feed
+ def _parseItem(self, item):
+ title = item.title
+ url = item.link
+
+ self._checkItemAuth(title, url)
+
+ if not title or not url:
+ logger.log(
+ u"The data returned from the " + self.provider.name + " feed is incomplete, this result is unusable",
+ logger.DEBUG)
+ return None
+
+ url = self._translateLinkURL(url)
+
+ logger.log(u"Adding item from RSS to cache: " + title, logger.DEBUG)
+
+ return self._addCacheEntry(title, url)
diff --git a/sickbeard/providers/nextgen.py b/sickbeard/providers/nextgen.py
index cbf7beb1..b4b92970 100644
--- a/sickbeard/providers/nextgen.py
+++ b/sickbeard/providers/nextgen.py
@@ -350,9 +350,8 @@ class NextGenCache(tvcache.TVCache):
if ci is not None:
cl.append(ci)
- if len(cl) > 0:
- myDB = self._getDB()
- myDB.mass_action(cl)
+ myDB = self._getDB()
+ myDB.mass_action(cl)
def _parseItem(self, item):
@@ -361,7 +360,7 @@ class NextGenCache(tvcache.TVCache):
if not title or not url:
return None
- logger.log(u"Attempting to cache item:" + title, logger.DEBUG)
+ logger.log(u"Attempting to cache item:[" + title +"]", logger.DEBUG)
return self._addCacheEntry(title, url)
diff --git a/sickbeard/providers/publichd.py b/sickbeard/providers/publichd.py
index 5eb5dff5..dcaeebe2 100644
--- a/sickbeard/providers/publichd.py
+++ b/sickbeard/providers/publichd.py
@@ -332,7 +332,7 @@ class PublicHDCache(tvcache.TVCache):
if not title or not url:
return None
- logger.log(u"Attempting to cache item:" + title, logger.DEBUG)
+ logger.log(u"Attempting to cache item:[" + title +"]", logger.DEBUG)
return self._addCacheEntry(title, url)
diff --git a/sickbeard/providers/scc.py b/sickbeard/providers/scc.py
index 4b5c4796..837745a3 100644
--- a/sickbeard/providers/scc.py
+++ b/sickbeard/providers/scc.py
@@ -340,9 +340,8 @@ class SCCCache(tvcache.TVCache):
if ci is not None:
cl.append(ci)
- if len(cl) > 0:
- myDB = self._getDB()
- myDB.mass_action(cl)
+ myDB = self._getDB()
+ myDB.mass_action(cl)
def _parseItem(self, item):
@@ -351,7 +350,7 @@ class SCCCache(tvcache.TVCache):
if not title or not url:
return None
- logger.log(u"Attempting to cache item:" + title, logger.DEBUG)
+ logger.log(u"Attempting to cache item:[" + title +"]", logger.DEBUG)
return self._addCacheEntry(title, url)
diff --git a/sickbeard/providers/speedcd.py b/sickbeard/providers/speedcd.py
index 1a6e0d71..9f89eb61 100644
--- a/sickbeard/providers/speedcd.py
+++ b/sickbeard/providers/speedcd.py
@@ -290,7 +290,7 @@ class SpeedCDCache(tvcache.TVCache):
if not title or not url:
return None
- logger.log(u"Attempting to cache item:" + title, logger.DEBUG)
+ logger.log(u"Attempting to cache item:[" + title +"]", logger.DEBUG)
return self._addCacheEntry(title, url)
diff --git a/sickbeard/providers/thepiratebay.py b/sickbeard/providers/thepiratebay.py
index b5962bd9..2108df82 100644
--- a/sickbeard/providers/thepiratebay.py
+++ b/sickbeard/providers/thepiratebay.py
@@ -421,9 +421,8 @@ class ThePirateBayCache(tvcache.TVCache):
if ci is not None:
cl.append(ci)
- if len(cl) > 0:
- myDB = self._getDB()
- myDB.mass_action(cl)
+ myDB = self._getDB()
+ myDB.mass_action(cl)
def _parseItem(self, item):
@@ -432,7 +431,7 @@ class ThePirateBayCache(tvcache.TVCache):
if not title or not url:
return None
- logger.log(u"Attempting to cache item:" + title, logger.DEBUG)
+ logger.log(u"Attempting to cache item:[" + title +"]", logger.DEBUG)
return self._addCacheEntry(title, url)
diff --git a/sickbeard/providers/torrentday.py b/sickbeard/providers/torrentday.py
index a3e4243b..9617eeee 100644
--- a/sickbeard/providers/torrentday.py
+++ b/sickbeard/providers/torrentday.py
@@ -302,9 +302,8 @@ class TorrentDayCache(tvcache.TVCache):
if ci is not None:
cl.append(ci)
- if len(cl) > 0:
- myDB = self._getDB()
- myDB.mass_action(cl)
+ myDB = self._getDB()
+ myDB.mass_action(cl)
def _parseItem(self, item):
@@ -313,7 +312,7 @@ class TorrentDayCache(tvcache.TVCache):
if not title or not url:
return None
- logger.log(u"Attempting to cache item:" + title, logger.DEBUG)
+ logger.log(u"Attempting to cache item:[" + title +"]", logger.DEBUG)
return self._addCacheEntry(title, url)
diff --git a/sickbeard/providers/torrentleech.py b/sickbeard/providers/torrentleech.py
index d5eb9f3c..eb8f394a 100644
--- a/sickbeard/providers/torrentleech.py
+++ b/sickbeard/providers/torrentleech.py
@@ -301,9 +301,8 @@ class TorrentLeechCache(tvcache.TVCache):
if ci is not None:
cl.append(ci)
- if len(cl) > 0:
- myDB = self._getDB()
- myDB.mass_action(cl)
+ myDB = self._getDB()
+ myDB.mass_action(cl)
def _parseItem(self, item):
@@ -312,7 +311,7 @@ class TorrentLeechCache(tvcache.TVCache):
if not title or not url:
return None
- logger.log(u"Attempting to cache item:" + title, logger.DEBUG)
+ logger.log(u"Attempting to cache item:[" + title +"]", logger.DEBUG)
return self._addCacheEntry(title, url)
diff --git a/sickbeard/search.py b/sickbeard/search.py
index 7bf40c63..b847a613 100644
--- a/sickbeard/search.py
+++ b/sickbeard/search.py
@@ -367,9 +367,6 @@ def searchProviders(queueItem, show, season, episodes, curProvider, seasonSearch
foundResults = {}
finalResults = []
- if manualSearch:
- curProvider.cache.updateCache()
-
# convert indexer numbering to scene numbering for searches
map(lambda x: x.convertToSceneNumbering, episodes)
@@ -404,7 +401,6 @@ def searchProviders(queueItem, show, season, episodes, curProvider, seasonSearch
highest_quality_overall = 0
for cur_episode in foundResults:
for cur_result in foundResults[cur_episode]:
- cur_result.queue_item = queueItem
if cur_result.quality != Quality.UNKNOWN and cur_result.quality > highest_quality_overall:
highest_quality_overall = cur_result.quality
logger.log(u"The highest quality of any match is " + Quality.qualityStrings[highest_quality_overall], logger.DEBUG)
@@ -572,4 +568,5 @@ def searchProviders(queueItem, show, season, episodes, curProvider, seasonSearch
finalResults.append(pickBestResult(foundResults[curEp], show))
- return finalResults
\ No newline at end of file
+ queueItem.results = finalResults
+ return queueItem
\ No newline at end of file
diff --git a/sickbeard/search_queue.py b/sickbeard/search_queue.py
index 9f6be560..a7cea779 100644
--- a/sickbeard/search_queue.py
+++ b/sickbeard/search_queue.py
@@ -22,113 +22,43 @@ import datetime
import Queue
import time
import traceback
+import threading
import sickbeard
from sickbeard import db, logger, common, exceptions, helpers
from sickbeard import generic_queue, scheduler
from sickbeard import search, failed_history, history
from sickbeard import ui
-from lib.concurrent import futures
+from sickbeard.snatch_queue import SnatchQueue
+from lib.concurrent.futures import as_completed
from lib.concurrent.futures.thread import ThreadPoolExecutor
+search_queue_lock = threading.Lock()
+
BACKLOG_SEARCH = 10
RSS_SEARCH = 20
FAILED_SEARCH = 30
MANUAL_SEARCH = 30
SNATCH = 40
-# snatch queues
-ManualSnatchQueue = Queue.PriorityQueue()
-RSSSnatchQueue = Queue.PriorityQueue()
-BacklogSnatchQueue = Queue.PriorityQueue()
-FailedSnatchQueue = Queue.PriorityQueue()
-
-SearchItemQueue = Queue.PriorityQueue()
-
-
-class SnatchQueue(generic_queue.GenericQueue):
- def __init__(self):
- generic_queue.GenericQueue.__init__(self)
- self.queue_name = "SNATCHQUEUE"
-
- def is_in_queue(self, show, episodes, quality):
- for cur_item in self.queue.queue:
- if cur_item.results.extraInfo[0] == show \
- and cur_item.results.episodes.sort() == episodes.sort() \
- and cur_item.results.quality >= quality:
- return True
- return False
-
- def add_item(self, item):
- # dynamically select our snatch queue
- if item.type == 'RSSSearchQueueItem':
- self.queue = RSSSnatchQueue
- elif item.type == 'ManualSearchQueueItem':
- self.queue = ManualSnatchQueue
- elif item.type == 'BacklogQueueItem':
- self.queue = BacklogSnatchQueue
- elif item.type == 'FailedQueueItem':
- self.queue = FailedSnatchQueue
- else:
- return
-
- # check if we already have a item ready to snatch with same or better quality score
- if not self.is_in_queue(item.results.extraInfo[0], item.results.episodes, item.results.quality):
- generic_queue.GenericQueue.add_item(self, item)
- else:
- logger.log(
- u"Not adding item [" + item.results.name + "] it's already in the queue with same or higher quality",
- logger.DEBUG)
-
-
-class SnatchQueueItem(generic_queue.QueueItem):
- def __init__(self, results, queue_item):
- generic_queue.QueueItem.__init__(self, 'Snatch', SNATCH)
- self.priority = generic_queue.QueuePriorities.HIGH
- self.thread_name = 'SNATCH-' + str(results.extraInfo[0].indexerid)
- self.results = results
- self.success = None
- self.queue_item = queue_item
- self.type = queue_item.type
-
- def execute(self):
- generic_queue.QueueItem.execute(self)
-
- # just use the first result for now
- logger.log(u"Downloading " + self.results.name + " from " + self.results.provider.name)
-
- result = search.snatchEpisode(self.results)
-
- if self.type == "ManualSearchQueueItem":
- providerModule = self.results.provider
- if not result:
- ui.notifications.error(
- 'Error while attempting to snatch ' + self.results.name + ', check your logs')
- elif providerModule == None:
- ui.notifications.error('Provider is configured incorrectly, unable to download')
-
- self.success = result
- self.queue_item.success = result
-
- generic_queue.QueueItem.finish(self.queue_item)
- generic_queue.QueueItem.finish(self)
class SearchQueue(generic_queue.GenericQueue):
def __init__(self):
generic_queue.GenericQueue.__init__(self)
self.queue_name = "SEARCHQUEUE"
- self.queue = SearchItemQueue
def is_in_queue(self, show, segment):
for cur_item in self.queue.queue:
- if isinstance(cur_item, BacklogQueueItem) and cur_item.show == show and cur_item.segment == segment:
- return True
+ with search_queue_lock:
+ if isinstance(cur_item, BacklogQueueItem) and cur_item.show == show and cur_item.segment == segment:
+ return True
return False
def is_ep_in_queue(self, ep_obj):
for cur_item in self.queue.queue:
- if isinstance(cur_item, ManualSearchQueueItem) and cur_item.ep_obj == ep_obj:
- return True
+ with search_queue_lock:
+ if isinstance(cur_item, ManualSearchQueueItem) and cur_item.ep_obj == ep_obj:
+ return True
return False
def pause_backlog(self):
@@ -143,15 +73,14 @@ class SearchQueue(generic_queue.GenericQueue):
def is_backlog_in_progress(self):
for cur_item in self.queue.queue + [self.currentItem]:
- if isinstance(cur_item, BacklogQueueItem):
- return True
+ with search_queue_lock:
+ if isinstance(cur_item, BacklogQueueItem):
+ return True
return False
def add_item(self, item):
- if isinstance(item, RSSSearchQueueItem):
- generic_queue.GenericQueue.add_item(self, item)
- elif isinstance(item, BacklogQueueItem) and not self.is_in_queue(item.show, item.segment):
+ if isinstance(item, BacklogQueueItem) and not self.is_in_queue(item.show, item.segment):
generic_queue.GenericQueue.add_item(self, item)
elif isinstance(item, ManualSearchQueueItem) and not self.is_ep_in_queue(item.ep_obj):
generic_queue.GenericQueue.add_item(self, item)
@@ -165,7 +94,6 @@ class ManualSearchQueueItem(generic_queue.QueueItem):
def __init__(self, ep_obj):
generic_queue.QueueItem.__init__(self, 'Manual Search', MANUAL_SEARCH)
self.priority = generic_queue.QueuePriorities.HIGH
- self.type = self.__class__.__name__
self.thread_name = 'MANUAL-' + str(ep_obj.show.indexerid)
self.success = None
self.show = ep_obj.show
@@ -174,113 +102,49 @@ class ManualSearchQueueItem(generic_queue.QueueItem):
def execute(self):
generic_queue.QueueItem.execute(self)
- fs = []
didSearch = False
providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive()]
try:
- with ThreadPoolExecutor(sickbeard.NUM_OF_THREADS) as executor:
- for provider in providers:
- didSearch = True
- logger.log("Beginning manual search for [" + self.ep_obj.prettyName() + "] on " + provider.name)
- executor.submit(
- search.searchProviders, self, self.show, self.ep_obj.season, [self.ep_obj], provider, False,
- True).add_done_callback(snatch_results)
- executor.shutdown(wait=True)
- except Exception, e:
+ for provider in providers:
+ logger.log("Beginning manual search for [" + self.ep_obj.prettyName() + "] on " + provider.name)
+ searchResult = search.searchProviders(self, self.show, self.ep_obj.season, [self.ep_obj], provider,
+ False,
+ True)
+
+ didSearch = True
+ if searchResult:
+ self.success = SnatchQueue().process_results(searchResult)
+ if self.success:
+ break
+
+ except Exception:
logger.log(traceback.format_exc(), logger.DEBUG)
+ stop = True
if not didSearch:
logger.log(
u"No NZB/Torrent providers found or enabled in your SickRage config. Please check your settings.",
logger.ERROR)
- if ManualSnatchQueue.empty():
+ if not self.success:
ui.notifications.message('No downloads were found',
"Couldn't find a download for %s" % self.ep_obj.prettyName())
logger.log(u"Unable to find a download for " + self.ep_obj.prettyName())
- else:
- # snatch all items in queue
- scheduler.Scheduler(SnatchQueue(), silent=True, runOnce=True, queue=ManualSnatchQueue).thread.start()
+ self.finish()
+
+ def finish(self):
+ # don't let this linger if something goes wrong
+ if self.success == None:
+ self.success = False
generic_queue.QueueItem.finish(self)
-class RSSSearchQueueItem(generic_queue.QueueItem):
- def __init__(self):
- generic_queue.QueueItem.__init__(self, 'RSS Search', RSS_SEARCH)
- self.thread_name = 'RSSFEED'
- self.type = self.__class__.__name__
-
- def execute(self):
- generic_queue.QueueItem.execute(self)
-
- results = False
- didSearch = False
-
- self._changeMissingEpisodes()
-
- providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive()]
-
- try:
- with ThreadPoolExecutor(sickbeard.NUM_OF_THREADS) as executor:
- for provider in providers:
- didSearch = True
- logger.log("Beginning RSS Feed search on " + provider.name)
- executor.submit(search.searchForNeededEpisodes, provider).add_done_callback(snatch_results)
- executor.shutdown(wait=True)
- except:
- logger.log(traceback.format_exc(), logger.DEBUG)
-
- if not didSearch:
- logger.log(
- u"No NZB/Torrent providers found or enabled in your SickRage config. Please check your settings.",
- logger.ERROR)
-
- if RSSSnatchQueue.empty():
- logger.log(u"No needed episodes found on the RSS feeds")
- else:
- # snatch all items in queue
- scheduler.Scheduler(SnatchQueue(), silent=True, runOnce=True, queue=RSSSnatchQueue).thread.start()
-
- generic_queue.QueueItem.finish(self)
-
- def _changeMissingEpisodes(self):
-
- logger.log(u"Changing all old missing episodes to status WANTED")
-
- curDate = datetime.date.today().toordinal()
-
- myDB = db.DBConnection()
- sqlResults = myDB.select("SELECT * FROM tv_episodes WHERE status = ? AND airdate < ?",
- [common.UNAIRED, curDate])
-
- for sqlEp in sqlResults:
-
- try:
- show = helpers.findCertainShow(sickbeard.showList, int(sqlEp["showid"]))
- except exceptions.MultipleShowObjectsException:
- logger.log(u"ERROR: expected to find a single show matching " + str(sqlEp["showid"]))
- return None
-
- if show == None:
- logger.log(u"Unable to find the show with ID " + str(
- sqlEp["showid"]) + " in your show list! DB value was " + str(sqlEp), logger.ERROR)
- return None
-
- ep = show.getEpisode(sqlEp["season"], sqlEp["episode"])
- with ep.lock:
- if ep.show.paused:
- ep.status = common.SKIPPED
- else:
- ep.status = common.WANTED
- ep.saveToDB()
-
class BacklogQueueItem(generic_queue.QueueItem):
def __init__(self, show, segment):
generic_queue.QueueItem.__init__(self, 'Backlog', BACKLOG_SEARCH)
self.priority = generic_queue.QueuePriorities.LOW
- self.type = self.__class__.__name__
self.thread_name = 'BACKLOG-' + str(show.indexerid)
self.show = show
@@ -315,7 +179,7 @@ class BacklogQueueItem(generic_queue.QueueItem):
def execute(self):
generic_queue.QueueItem.execute(self)
- results = False
+ fs = []
didSearch = False
# check if we want to search for season packs instead of just season/episode
@@ -327,15 +191,18 @@ class BacklogQueueItem(generic_queue.QueueItem):
providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive()]
try:
- with ThreadPoolExecutor(sickbeard.NUM_OF_THREADS) as executor:
- for provider in providers:
- didSearch = True
- logger.log("Beginning backlog search for [" + str(self.segment) + "] on " + provider.name)
- executor.submit(
- search.searchProviders, self, self.show, self.segment, self.wantedEpisodes, provider,
- seasonSearch, False).add_done_callback(snatch_results)
- executor.shutdown(wait=True)
- except Exception, e:
+ for provider in providers:
+ logger.log("Beginning backlog search for [" + str(self.segment) + "] on " + provider.name)
+ searchResult = search.searchProviders(self, self.show, self.segment, self.wantedEpisodes, provider,
+ seasonSearch, False)
+
+ didSearch = True
+ if searchResult:
+ self.success = SnatchQueue().process_results(searchResult)
+ if self.success:
+ break
+
+ except Exception:
logger.log(traceback.format_exc(), logger.DEBUG)
if not didSearch:
@@ -343,11 +210,8 @@ class BacklogQueueItem(generic_queue.QueueItem):
u"No NZB/Torrent providers found or enabled in your SickRage config. Please check your settings.",
logger.ERROR)
- if BacklogSnatchQueue.empty():
+ if not self.success:
logger.log(u"No needed episodes found during backlog search")
- else:
- # snatch all items in queue
- scheduler.Scheduler(SnatchQueue(), silent=True, runOnce=True, queue=BacklogSnatchQueue).thread.start()
self.finish()
@@ -356,8 +220,6 @@ class BacklogQueueItem(generic_queue.QueueItem):
# check through the list of statuses to see if we want any
for curStatusResult in statusResults:
- time.sleep(1)
-
curCompositeStatus = int(curStatusResult["status"])
curStatus, curQuality = common.Quality.splitCompositeStatus(curCompositeStatus)
episode = int(curStatusResult["episode"])
@@ -380,7 +242,6 @@ class FailedQueueItem(generic_queue.QueueItem):
def __init__(self, show, episodes):
generic_queue.QueueItem.__init__(self, 'Retry', FAILED_SEARCH)
self.priority = generic_queue.QueuePriorities.HIGH
- self.type = self.__class__.__name__
self.thread_name = 'RETRY-' + str(show.indexerid)
self.show = show
self.episodes = episodes
@@ -389,13 +250,11 @@ class FailedQueueItem(generic_queue.QueueItem):
def execute(self):
generic_queue.QueueItem.execute(self)
- results = False
+ fs = []
didSearch = False
-
episodes = []
for i, epObj in enumerate(episodes):
- time.sleep(1)
logger.log(
"Beginning failed download search for " + epObj.prettyName())
@@ -412,14 +271,16 @@ class FailedQueueItem(generic_queue.QueueItem):
providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive()]
try:
- with ThreadPoolExecutor(sickbeard.NUM_OF_THREADS) as executor:
- for provider in providers:
- didSearch = True
- executor.submit(
- search.searchProviders, self, self.show, self.episodes[0].season, self.episodes, provider,
- False,
- True).add_done_callback(snatch_results)
- executor.shutdown(wait=True)
+ for provider in providers:
+ searchResult = search.searchProviders(self.show, self.episodes[0].season, self.episodes, provider,
+ False, True)
+
+ didSearch = True
+ if searchResult:
+ self.success = SnatchQueue().process_results(searchResult)
+ if self.success:
+ break
+
except Exception, e:
logger.log(traceback.format_exc(), logger.DEBUG)
@@ -428,17 +289,7 @@ class FailedQueueItem(generic_queue.QueueItem):
u"No NZB/Torrent providers found or enabled in your SickRage config. Please check your settings.",
logger.ERROR)
- if FailedSnatchQueue.empty():
+ if not self.success:
logger.log(u"No needed episodes found on the RSS feeds")
- else:
- # snatch all items in queue
- scheduler.Scheduler(SnatchQueue(), silent=True, runOnce=True, queue=FailedSnatchQueue).thread.start()
- self.finish()
-
-
-# send to snatch queue
-def snatch_results(f):
- for result in f.result():
- snatch_queue_item = SnatchQueueItem(result, result.queue_item)
- SnatchQueue().add_item(snatch_queue_item)
+ self.finish()
\ No newline at end of file
diff --git a/sickbeard/show_queue.py b/sickbeard/show_queue.py
index 22d2aa3d..7a6a37f8 100644
--- a/sickbeard/show_queue.py
+++ b/sickbeard/show_queue.py
@@ -19,6 +19,7 @@
from __future__ import with_statement
import traceback
+import threading
import Queue
import sickbeard
@@ -31,18 +32,18 @@ from sickbeard import generic_queue
from sickbeard import name_cache
from sickbeard.exceptions import ex
-ShowItemQueue = Queue.PriorityQueue()
+show_queue_lock = threading.Lock()
+show_queue = Queue.Queue()
class ShowQueue(generic_queue.GenericQueue):
def __init__(self):
generic_queue.GenericQueue.__init__(self)
self.queue_name = "SHOWQUEUE"
- self.queue = ShowItemQueue
-
+ self.queue = show_queue
def _isInQueue(self, show, actions):
- return show in [x.show for x in self.queue.queue if x.action_id in actions] if self.queue.qsize() > 0 else []
+ return show in [x.show for x in self.queue.get() if x.action_id in actions] if not self.queue.empty() else []
def _isBeingSomethinged(self, show, actions):
return self.currentItem != None and show == self.currentItem.show and \
@@ -76,7 +77,8 @@ class ShowQueue(generic_queue.GenericQueue):
return self._isBeingSomethinged(show, (ShowQueueActions.SUBTITLE,))
def _getLoadingShowList(self):
- return [x for x in self.queue.queue + [self.currentItem] if x != None and x.isLoading] if self.queue.qsize() > 0 else []
+ return [x for x in self.queue.get() if x != None and x.isLoading] + [self.currentItem] if not self.queue.empty() else []
+
loadingShowList = property(_getLoadingShowList)
@@ -180,8 +182,7 @@ class ShowQueueItem(generic_queue.QueueItem):
self.show = show
def isInQueue(self):
- return self in sickbeard.showQueueScheduler.action.queue + [
- sickbeard.showQueueScheduler.action.currentItem] #@UndefinedVariable
+ return self in sickbeard.showQueueScheduler.action.queue.queue + [sickbeard.showQueueScheduler.action.currentItem]
def _getName(self):
return str(self.show.indexerid)
diff --git a/sickbeard/snatch_queue.py b/sickbeard/snatch_queue.py
new file mode 100644
index 00000000..32b8dbb1
--- /dev/null
+++ b/sickbeard/snatch_queue.py
@@ -0,0 +1,83 @@
+import Queue
+import threading
+
+import sickbeard
+from sickbeard import logger, search, generic_queue, ui
+from sickbeard.common import Quality
+
+snatch_queue_lock = threading.Lock()
+
+class SnatchQueue(generic_queue.GenericQueue):
+ def __init__(self):
+ generic_queue.GenericQueue.__init__(self)
+ self.queue_name = "SNATCHQUEUE"
+
+ # snatch queues
+ self.ManualQueue = Queue.Queue()
+ self.BacklogQueue = Queue.Queue()
+ self.FailedQueue = Queue.Queue()
+
+ def is_in_queue(self, queue, show, episodes, quality):
+ for i, cur_item in enumerate(queue.queue):
+ if cur_item.results.show == show and cur_item.results.episodes.sort() == episodes.sort():
+ if cur_item.results.quality < quality:
+ queue.queue.pop(i)
+ return False
+ return True
+ return False
+
+ def add_item(self, item):
+ resultsKeep = []
+ for result in item.results:
+ show = result.extraInfo[0]
+ episodes = result.episodes
+ quality = result.quality
+
+ # check if we already have a item ready to snatch with same or better quality score
+ if not self.is_in_queue(self.queue, show, episodes, quality):
+ generic_queue.GenericQueue.add_item(self, item)
+ resultsKeep.append(result)
+ logger.log(
+ u"Adding item [" + result.name + "] to snatch queue",
+ logger.DEBUG)
+ else:
+ logger.log(
+ u"Not adding item [" + result.name + "] it's already in the queue with same or higher quality",
+ logger.DEBUG)
+
+ # update item with new results we want to snatch and disgard the rest
+ item.results = resultsKeep
+
+ def snatch_item(self, item):
+ for result in item.results:
+ # just use the first result for now
+ logger.log(u"Downloading " + result.name + " from " + result.provider.name)
+ status = search.snatchEpisode(result)
+ item.success = status
+ generic_queue.QueueItem.finish(item)
+ return status
+
+ def process_results(self, item):
+ # dynamically select our snatch queue
+ if isinstance(item, sickbeard.search_queue.ManualSearchQueueItem):
+ self.queue = self.ManualQueue
+ elif isinstance(item, sickbeard.search_queue.BacklogQueueItem):
+ self.queue = self.BacklogQueue
+ elif isinstance(item, sickbeard.search_queue.FailedQueueItem):
+ self.queue = self.FailedQueue
+
+ for result in item.results:
+ logger.log(u"Checking if we should snatch " + result.name, logger.DEBUG)
+ show_obj = result.episodes[0].show
+ any_qualities, best_qualities = Quality.splitQuality(show_obj.quality)
+
+ # if there is a redownload that's higher than this then we definitely need to keep looking
+ if best_qualities and result.quality == max(best_qualities):
+ return self.snatch_item(item)
+
+ # if there's no redownload that's higher (above) and this is the highest initial download then we're good
+ elif any_qualities and result.quality in any_qualities:
+ return self.snatch_item(item)
+
+ # Add item to queue if we couldn't find a match to snatch
+ self.add_item(item)
diff --git a/sickbeard/tvcache.py b/sickbeard/tvcache.py
index 3ca75fb9..c63be80f 100644
--- a/sickbeard/tvcache.py
+++ b/sickbeard/tvcache.py
@@ -15,6 +15,9 @@
#
# You should have received a copy of the GNU General Public License
# along with Sick Beard. If not, see .
+
+from __future__ import with_statement
+
import os
import time
@@ -23,23 +26,24 @@ import sqlite3
import urllib
import urlparse
import re
-
+import threading
import sickbeard
-from shove import Shove
-from feedcache import cache
+from lib.shove import Shove
+from lib.feedcache import cache
from sickbeard import db
from sickbeard import logger
from sickbeard.common import Quality
from sickbeard import helpers, show_name_helpers
-from sickbeard.exceptions import MultipleShowObjectsException, ex
+from sickbeard.exceptions import MultipleShowObjectsException
from sickbeard.exceptions import AuthException
from sickbeard import encodingKludge as ek
from name_parser.parser import NameParser, InvalidNameException
+cache_lock = threading.Lock()
class CacheDBConnection(db.DBConnection):
def __init__(self, providerName):
@@ -93,6 +97,40 @@ class TVCache():
def _checkItemAuth(self, title, url):
return True
+ def updateCache(self):
+ if not self.shouldUpdate():
+ return
+
+ if self._checkAuth(None):
+ data = self._getRSSData()
+
+ # as long as the http request worked we count this as an update
+ if data:
+ self.setLastUpdate()
+ else:
+ return []
+
+ # now that we've loaded the current RSS feed lets delete the old cache
+ logger.log(u"Clearing " + self.provider.name + " cache and updating with new information")
+ self._clearCache()
+
+ if self._checkAuth(data):
+ items = data.entries
+ cl = []
+ for item in items:
+ ci = self._parseItem(item)
+ if ci is not None:
+ cl.append(ci)
+
+ myDB = self._getDB()
+ myDB.mass_action(cl)
+
+ else:
+ raise AuthException(
+ u"Your authentication credentials for " + self.provider.name + " are incorrect, check your config")
+
+ return []
+
def getRSSFeed(self, url, post_data=None):
# create provider storaqe cache
storage = Shove('sqlite:///' + ek.ek(os.path.join, sickbeard.CACHE_DIR, self.provider.name) + '.db')
@@ -121,50 +159,16 @@ class TVCache():
return f
- def updateCache(self):
-
- if not self.shouldUpdate():
- return
-
- if self._checkAuth(None):
- data = self._getRSSData()
-
- # as long as the http request worked we count this as an update
- if data:
- self.setLastUpdate()
- else:
- return []
-
- # now that we've loaded the current RSS feed lets delete the old cache
- logger.log(u"Clearing " + self.provider.name + " cache and updating with new information")
- self._clearCache()
-
- if self._checkAuth(data):
- items = data.entries
- ql = []
- for item in items:
- qi = self._parseItem(item)
- if qi is not None:
- ql.append(qi)
-
- if len(ql):
- myDB = self._getDB()
- myDB.mass_action(ql)
-
- else:
- raise AuthException(
- u"Your authentication credentials for " + self.provider.name + " are incorrect, check your config")
-
- return []
def _translateTitle(self, title):
return title.replace(' ', '.')
+
def _translateLinkURL(self, url):
return url.replace('&', '&')
- def _parseItem(self, item):
+ def _parseItem(self, item):
title = item.title
url = item.link
@@ -197,8 +201,8 @@ class TVCache():
return datetime.datetime.fromtimestamp(lastTime)
- def setLastUpdate(self, toDate=None):
+ def setLastUpdate(self, toDate=None):
if not toDate:
toDate = datetime.datetime.today()
@@ -207,8 +211,10 @@ class TVCache():
{'time': int(time.mktime(toDate.timetuple()))},
{'provider': self.providerID})
+
lastUpdate = property(_getLastUpdate)
+
def shouldUpdate(self):
# if we've updated recently then skip the update
if datetime.datetime.today() - self.lastUpdate < datetime.timedelta(minutes=self.minTime):
@@ -218,13 +224,10 @@ class TVCache():
return True
- def _addCacheEntry(self, name, url, quality=None):
- cacheResult = sickbeard.name_cache.retrieveNameFromCache(name)
- if cacheResult:
- logger.log(u"Found Indexer ID:[" + repr(cacheResult) + "], using that for [" + str(name) + "}",
- logger.DEBUG)
- return None
+ def _addCacheEntry(self, name, url, quality=None):
+ indexerid = None
+ in_cache = False
# if we don't have complete info then parse the filename to get it
try:
@@ -242,9 +245,34 @@ class TVCache():
logger.log(u"No series name retrieved from " + name + ", unable to cache it", logger.DEBUG)
return None
- showObj = sickbeard.name_cache.retrieveShowFromCache(parse_result.series_name)
+ cacheResult = sickbeard.name_cache.retrieveNameFromCache(name)
+ if cacheResult:
+ in_cache = True
+ indexerid = int(cacheResult)
+
+ if not indexerid:
+ name_list = show_name_helpers.sceneToNormalShowNames(parse_result.series_name)
+ for cur_name in name_list:
+ if not indexerid:
+ for curShow in sickbeard.showList:
+ if show_name_helpers.isGoodResult(cur_name, curShow, False):
+ indexerid = int(curShow.indexerid)
+ break
+
+ if not indexerid:
+ # do a scene reverse-lookup to get a list of all possible names
+ scene_id = sickbeard.scene_exceptions.get_scene_exception_by_name(cur_name)
+ if scene_id:
+ indexerid = int(scene_id)
+ break
+
+ showObj = None
+ if indexerid:
+ logger.log(u"Found Indexer ID: [" + str(indexerid) + "], for [" + str(cur_name) + "}", logger.DEBUG)
+ showObj = helpers.findCertainShow(sickbeard.showList, indexerid)
+
if not showObj:
- logger.log(u"Show is not in our list of watched shows [" + parse_result.series_name + "], not caching ...", logger.DEBUG)
+ logger.log(u"No match for show: [" + parse_result.series_name + "], not caching ...", logger.DEBUG)
return None
season = episodes = None
@@ -254,7 +282,7 @@ class TVCache():
airdate = parse_result.air_date.toordinal() or parse_result.sports_event_date.toordinal()
sql_results = myDB.select(
"SELECT season, episode FROM tv_episodes WHERE showid = ? AND indexer = ? AND airdate = ?",
- [showObj.indexerid, showObj.indexer, airdate])
+ [indexerid, showObj.indexer, airdate])
if sql_results > 0:
season = int(sql_results[0]["season"])
episodes = [int(sql_results[0]["episode"])]
@@ -277,18 +305,21 @@ class TVCache():
name = unicode(name, 'utf-8')
logger.log(u"Added RSS item: [" + name + "] to cache: [" + self.providerID + "]", logger.DEBUG)
- sickbeard.name_cache.addNameToCache(name, showObj.indexerid)
+
+ if not in_cache:
+ sickbeard.name_cache.addNameToCache(name, indexerid)
+
return [
"INSERT INTO [" + self.providerID + "] (name, season, episodes, indexerid, url, time, quality) VALUES (?,?,?,?,?,?,?)",
- [name, season, episodeText, showObj.indexerid, url, curTimestamp, quality]]
+ [name, season, episodeText, indexerid, url, curTimestamp, quality]]
def searchCache(self, episode, manualSearch=False):
neededEps = self.findNeededEpisodes(episode, manualSearch)
return neededEps
- def listPropers(self, date=None, delimiter="."):
+ def listPropers(self, date=None, delimiter="."):
myDB = self._getDB()
sql = "SELECT * FROM [" + self.providerID + "] WHERE name LIKE '%.PROPER.%' OR name LIKE '%.REPACK.%'"
@@ -298,6 +329,7 @@ class TVCache():
return filter(lambda x: x['indexerid'] != 0, myDB.select(sql))
+
def findNeededEpisodes(self, epObj=None, manualSearch=False):
neededEps = {}
@@ -319,7 +351,7 @@ class TVCache():
# get the show object, or if it's not one of our shows then ignore it
try:
showObj = helpers.findCertainShow(sickbeard.showList, int(curResult["indexerid"]))
- except (MultipleShowObjectsException):
+ except MultipleShowObjectsException:
showObj = None
if not showObj:
@@ -365,3 +397,4 @@ class TVCache():
neededEps[epObj].append(result)
return neededEps
+
diff --git a/sickbeard/webapi.py b/sickbeard/webapi.py
index 8c707944..38dbf751 100644
--- a/sickbeard/webapi.py
+++ b/sickbeard/webapi.py
@@ -1368,14 +1368,12 @@ class CMD_SickBeardCheckScheduler(ApiCall):
backlogPaused = sickbeard.searchQueueScheduler.action.is_backlog_paused() #@UndefinedVariable
backlogRunning = sickbeard.searchQueueScheduler.action.is_backlog_in_progress() #@UndefinedVariable
- searchStatus = sickbeard.currentSearchScheduler.action.amActive #@UndefinedVariable
- nextSearch = str(sickbeard.currentSearchScheduler.timeLeft()).split('.')[0]
nextBacklog = sickbeard.backlogSearchScheduler.nextRun().strftime(dateFormat).decode(sickbeard.SYS_ENCODING)
myDB.connection.close()
data = {"backlog_is_paused": int(backlogPaused), "backlog_is_running": int(backlogRunning),
"last_backlog": _ordinal_to_dateForm(sqlResults[0]["last_backlog"]),
- "search_is_running": int(searchStatus), "next_search": nextSearch, "next_backlog": nextBacklog}
+ "next_backlog": nextBacklog}
return _responds(RESULT_SUCCESS, data)
@@ -1424,27 +1422,6 @@ class CMD_SickBeardDeleteRootDir(ApiCall):
return _responds(RESULT_SUCCESS, _getRootDirs(), msg="Root directory deleted")
-class CMD_SickBeardForceSearch(ApiCall):
- _help = {"desc": "force the episode search early"
- }
-
- def __init__(self, args, kwargs):
- # required
- # optional
- # super, missing, help
- ApiCall.__init__(self, args, kwargs)
-
- def run(self):
- """ force the episode search early """
- # Changing all old missing episodes to status WANTED
- # Beginning search for new episodes on RSS
- # Searching all providers for any needed episodes
- result = sickbeard.currentSearchScheduler.forceRun()
- if result:
- return _responds(RESULT_SUCCESS, msg="Episode search forced")
- return _responds(RESULT_FAILURE, msg="Can not search for episode")
-
-
class CMD_SickBeardGetDefaults(ApiCall):
_help = {"desc": "get sickbeard user defaults"}
@@ -2604,7 +2581,6 @@ _functionMaper = {"help": CMD_Help,
"sb.addrootdir": CMD_SickBeardAddRootDir,
"sb.checkscheduler": CMD_SickBeardCheckScheduler,
"sb.deleterootdir": CMD_SickBeardDeleteRootDir,
- "sb.forcesearch": CMD_SickBeardForceSearch,
"sb.getdefaults": CMD_SickBeardGetDefaults,
"sb.getmessages": CMD_SickBeardGetMessages,
"sb.getrootdirs": CMD_SickBeardGetRootDirs,
diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py
index 847b0247..7b12f657 100644
--- a/sickbeard/webserve.py
+++ b/sickbeard/webserve.py
@@ -204,24 +204,11 @@ class ManageSearches:
#t.backlogPI = sickbeard.backlogSearchScheduler.action.getProgressIndicator()
t.backlogPaused = sickbeard.searchQueueScheduler.action.is_backlog_paused() # @UndefinedVariable
t.backlogRunning = sickbeard.searchQueueScheduler.action.is_backlog_in_progress() # @UndefinedVariable
- t.searchStatus = sickbeard.currentSearchScheduler.action.amActive # @UndefinedVariable
t.submenu = ManageMenu()
return _munge(t)
- @cherrypy.expose
- def forceSearch(self):
-
- # force it to run the next time it looks
- result = sickbeard.currentSearchScheduler.forceRun()
- if result:
- logger.log(u"Search forced")
- ui.notifications.message('Episode search started',
- 'Note: RSS feeds may not be updated if retrieved recently')
-
- redirect("/manage/manageSearches/")
-
@cherrypy.expose
def pauseBacklog(self, paused=None):
if paused == "1":