#!/usr/bin/env python # -*- coding: utf-8 -*- """ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . @author: RaNaN """ from Queue import Queue from time import sleep, time from traceback import print_exc from sys import exc_clear from pycurl import error from module.plugins.Base import Fail, Retry, Abort from module.plugins.Hoster import Reconnect, SkipDownload from module.network.HTTPRequest import BadHeader from BaseThread import BaseThread class DownloadThread(BaseThread): """thread for downloading files from 'real' hoster plugins""" def __init__(self, manager): """Constructor""" BaseThread.__init__(self, manager) self.queue = Queue() # job queue self.active = False self.start() def run(self): """run method""" pyfile = None while True: del pyfile self.active = self.queue.get() pyfile = self.active if self.active == "quit": self.active = False self.m.threads.remove(self) return True try: if not pyfile.hasPlugin(): continue #this pyfile was deleted while queuing pyfile.plugin.checkForSameFiles(starting=True) self.log.info(_("Download starts: %s" % pyfile.name)) # start download self.core.addonManager.downloadPreparing(pyfile) pyfile.plugin.preprocessing(self) self.log.info(_("Download finished: %s") % pyfile.name) self.core.addonManager.downloadFinished(pyfile) self.core.files.checkPackageFinished(pyfile) except NotImplementedError: self.log.error(_("Plugin %s is missing a function.") % pyfile.pluginname) pyfile.setStatus("failed") pyfile.error = "Plugin does not work" self.clean(pyfile) continue except Abort: try: self.log.info(_("Download aborted: %s") % pyfile.name) except: pass pyfile.setStatus("aborted") self.clean(pyfile) continue except Reconnect: self.queue.put(pyfile) #pyfile.req.clearCookies() while self.m.reconnecting.isSet(): sleep(0.5) continue except Retry, e: reason = e.args[0] self.log.info(_("Download restarted: %(name)s | %(msg)s") % {"name": pyfile.name, "msg": reason}) self.queue.put(pyfile) continue except Fail, e: msg = e.args[0] if msg == "offline": pyfile.setStatus("offline") self.log.warning(_("Download is offline: %s") % pyfile.name) elif msg == "temp. offline": pyfile.setStatus("temp. offline") self.log.warning(_("Download is temporary offline: %s") % pyfile.name) else: pyfile.setStatus("failed") self.log.warning(_("Download failed: %(name)s | %(msg)s") % {"name": pyfile.name, "msg": msg}) pyfile.error = msg self.core.addonManager.downloadFailed(pyfile) self.clean(pyfile) continue except error, e: if len(e.args) == 2: code, msg = e.args else: code = 0 msg = e.args self.log.debug("pycurl exception %s: %s" % (code, msg)) if code in (7, 18, 28, 52, 56): self.log.warning(_("Couldn't connect to host or connection reset, waiting 1 minute and retry.")) wait = time() + 60 pyfile.waitUntil = wait pyfile.setStatus("waiting") while time() < wait: sleep(1) if pyfile.abort: break if pyfile.abort: self.log.info(_("Download aborted: %s") % pyfile.name) pyfile.setStatus("aborted") self.clean(pyfile) else: self.queue.put(pyfile) continue else: pyfile.setStatus("failed") self.log.error("pycurl error %s: %s" % (code, msg)) if self.core.debug: print_exc() self.writeDebugReport(pyfile.plugin.__name__, pyfile) self.core.addonManager.downloadFailed(pyfile) self.clean(pyfile) continue except SkipDownload, e: pyfile.setStatus("skipped") self.log.info(_("Download skipped: %(name)s due to %(plugin)s") % {"name": pyfile.name, "plugin": e.message}) self.clean(pyfile) self.core.files.checkPackageFinished(pyfile) self.active = False self.core.files.save() continue except Exception, e: if isinstance(e, BadHeader) and e.code == 500: pyfile.setStatus("temp. offline") self.log.warning(_("Download is temporary offline: %s") % pyfile.name) pyfile.error = _("Internal Server Error") else: pyfile.setStatus("failed") self.log.warning(_("Download failed: %(name)s | %(msg)s") % {"name": pyfile.name, "msg": str(e)}) pyfile.error = str(e) if self.core.debug: print_exc() self.writeDebugReport(pyfile.plugin.__name__, pyfile) self.core.addonManager.downloadFailed(pyfile) self.clean(pyfile) continue finally: self.core.files.save() pyfile.checkIfProcessed() exc_clear() #pyfile.plugin.req.clean() self.active = False pyfile.finishIfDone() self.core.files.save() def put(self, job): """assign a job to the thread""" self.queue.put(job) def stop(self): """stops the thread""" self.put("quit")