⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 torrentqueue.py

📁 BitTorrent(简称BT
💻 PY
📖 第 1 页 / 共 2 页
字号:
            if t.finishtime > mintime:                if t.uptotal < t.downtotal * minratio:                    continue            self.change_torrent_state(infohash, RUNNING, KNOWN)            break        if self.running_torrents and self.last_save_time < now - 300:            self._dump_state()    def _check_queue(self):        if self.starting_torrent is not None or self.config['pause']:            return        for infohash in self.running_torrents:            if self.torrents[infohash].state == RUN_QUEUED:                self.starting_torrent = infohash                t = self.torrents[infohash]                t.state = RUNNING                t.finishtime = None                t.dl = self.multitorrent.start_torrent(t.metainfo, self.config,                                                       self, t.dlpath)                return        if not self.queue or len(self.running_torrents) >= \               self.config['def_running_torrents']:            return        infohash = self.queue.pop(0)        self.starting_torrent = infohash        t = self.torrents[infohash]        assert t.state == QUEUED        t.state = RUNNING        t.finishtime = None        self.running_torrents.append(infohash)        t.dl = self.multitorrent.start_torrent(t.metainfo, self.config, self,                                               t.dlpath)        self._send_state(infohash)    def _send_state(self, infohash):        t = self.torrents[infohash]        state = t.state        if state == RUN_QUEUED:            state = RUNNING        pos = None        if state in (KNOWN, RUNNING, QUEUED):            l = self._get_list(state)            if l[-1] != infohash:                pos = l.index(infohash)        self.run_ui_task(self.ui.torrent_state_changed, infohash, state,                        t.completion, t.uptotal_old, t.downtotal_old, pos)    def _stop_running(self, infohash):        t = self.torrents[infohash]        if t.state == RUN_QUEUED:            self.running_torrents.remove(infohash)            t.state = KNOWN            return True        assert t.state == RUNNING        t.dl.shutdown()        if infohash == self.starting_torrent:            self.starting_torrent = None        try:            self.running_torrents.remove(infohash)        except ValueError:            self.other_torrents.remove(infohash)            return False        else:            t.state = KNOWN            totals = t.dl.get_total_transfer()            t.uptotal_old += totals[0]            t.uptotal = t.uptotal_old            t.downtotal_old += totals[1]            t.downtotal = t.downtotal_old            t.dl = None            t.completion = self.multitorrent.get_completion(self.config,                                               t.metainfo, t.dlpath)            return True    def external_command(self, action, data):        if action == 'start_torrent':            self.start_new_torrent(data)        elif action == 'show_error':            self.global_error(ERROR, data)        elif action == 'no-op':            pass    def remove_torrent(self, infohash):        if infohash not in self.torrents:            return        state = self.torrents[infohash].state        if state == QUEUED:            self.queue.remove(infohash)        elif state in (RUNNING, RUN_QUEUED):            self._stop_running(infohash)            self._check_queue()        else:            self.other_torrents.remove(infohash)        self.run_ui_task(self.ui.removed_torrent, infohash)        del self.torrents[infohash]        filename = os.path.join(self.config['data_dir'], 'metainfo',                                infohash.encode('hex'))        try:            os.remove(filename)        except Exception, e:            self.global_error(WARNING, 'Could not delete cached metainfo file:'                              + str(e))        self._dump_state()    def set_save_location(self, infohash, dlpath):        torrent = self.torrents.get(infohash)        if torrent is None or torrent.state == RUNNING:            return        torrent.dlpath = dlpath        torrent.completion = self.multitorrent.get_completion(self.config,                                                   torrent.metainfo, dlpath)        if torrent.state == ASKING_LOCATION:            torrent.state = KNOWN            self.change_torrent_state(infohash, KNOWN, QUEUED)        else:            self._send_state(infohash)            self._dump_state()    def start_new_torrent(self, data):        t = TorrentInfo()        try:            t.metainfo = ConvertedMetainfo(bdecode(data))        except Exception, e:            self.global_error(ERROR, "This is not a valid torrent file. (%s)"                              % str(e))            return        infohash = t.metainfo.infohash        if infohash in self.torrents:            self.error(t.metainfo, ERROR, "A torrent with the same contents "                       "(infohash) is already open. Cannot start another.")            return        path = os.path.join(self.config['data_dir'], 'metainfo',                            infohash.encode('hex'))        try:            f = file(path, 'wb')            f.write(data)            f.close()        except Exception, e:            try:                f.close()            except:                pass            self.global_error(ERROR, 'Could not write file '+path+' ('+str(e)+                              '), torrent will not be restarted correctly on '                              'client restart')        self.torrents[infohash] = t        t.state = ASKING_LOCATION        self.other_torrents.append(infohash)        self._dump_state()        self.run_ui_task(self.ui.new_displayed_torrent, infohash,                         t.metainfo, None, ASKING_LOCATION)        def show_error(level, text):            self.run_ui_task(self.ui.error, infohash, level, text)        t.metainfo.show_encoding_errors(show_error)    def set_config(self, option, value):        if option not in self.config:            return        oldvalue = self.config[option]        self.config[option] = value        if option == 'pause':            if value and not oldvalue:                self.set_zero_running_torrents()            elif not value and oldvalue:                self._check_queue()        else:            self.multitorrent.set_option(option, value)            for infohash in list(self.running_torrents):                torrent = self.torrents[infohash]                if torrent.state == RUNNING:                    torrent.dl.set_option(option, value)                    if option in ('forwarded_port', 'maxport'):                        torrent.dl.change_port()        self._dump_config()    def request_status(self, infohash, want_spew, want_fileinfo):        torrent = self.torrents.get(infohash)        if torrent is None or torrent.state != RUNNING:            return        status = torrent.dl.get_status(want_spew, want_fileinfo)        if torrent.finishtime is not None:            now = bttime()            uptotal = status['upTotal'] + torrent.uptotal_old            downtotal = status['downTotal'] + torrent.downtotal_old            ulspeed = status['upRate2']            if self.queue:                ratio = self.config['next_torrent_ratio'] / 100            else:                ratio = self.config['last_torrent_ratio'] / 100            if ratio <= 0 or ulspeed <= 0:                rem = 1e99            else:                rem = (downtotal * ratio - uptotal) / ulspeed            if self.queue:                rem = min(rem, torrent.finishtime +                          self.config['next_torrent_time'] * 60 - now)            rem = max(rem, torrent.finishtime + 120 - now)            if rem <= 0:                rem = 1            if rem == 1e99:                rem = None            status['timeEst'] = rem        self.run_ui_task(self.ui.update_status, infohash, status)    def _get_list(self, state):        if state == KNOWN:            return self.other_torrents        elif state == QUEUED:            return self.queue        elif state in (RUNNING, RUN_QUEUED):            return self.running_torrents        assert False    def change_torrent_state(self, infohash, oldstate, newstate=None,                     pred=None, succ=None, replaced=None, force_running=False):        self._check_version()        t = self.torrents.get(infohash)        if t is None or (t.state != oldstate and not (t.state == RUN_QUEUED and                                                      oldstate == RUNNING)):            return        if newstate is None:            newstate = oldstate        assert oldstate in (KNOWN, QUEUED, RUNNING)        assert newstate in (KNOWN, QUEUED, RUNNING)        pos = None        if oldstate != RUNNING and newstate == RUNNING and replaced is None:            if len(self.running_torrents) >= (force_running and self.config[               'max_running_torrents'] or self.config['def_running_torrents']):                if force_running:                    self.global_error(ERROR,                                      "Can't run more than %d torrents "\                                      "simultaneously. For more info see the"\                                      " FAQ at %s."%                                      (self.config['max_running_torrents'],                                       FAQ_URL))                newstate = QUEUED                pos = 0        l = self._get_list(newstate)        if newstate == oldstate:            origpos = l.index(infohash)            del l[origpos]            if pos is None:                pos = decode_position(l, pred, succ, -1)            if pos == -1 or l == origpos:                l.insert(origpos, infohash)                return            l.insert(pos, infohash)            self._dump_state()            self.run_ui_task(self.ui.reorder_torrent, infohash, pos)            return        if pos is None:            pos = decode_position(l, pred, succ)        if newstate == RUNNING:            newstate = RUN_QUEUED            if replaced and len(self.running_torrents) >= \               self.config['def_running_torrents']:                t2 = self.torrents.get(replaced)                if t2 is None or t2.state not in (RUNNING, RUN_QUEUED):                    return                if self.running_torrents.index(replaced) < pos:                    pos -= 1                if self._stop_running(replaced):                    t2.state = QUEUED                    self.queue.insert(0, replaced)                    self._send_state(replaced)                else:                    self.other_torrents.append(replaced)        if oldstate == RUNNING:            if newstate == QUEUED and len(self.running_torrents) <= \                   self.config['def_running_torrents'] and pos == 0:                return            if not self._stop_running(infohash):                if newstate == KNOWN:                    self.other_torrents.insert(pos, infohash)                    self.run_ui_task(self.ui.reorder_torrent, infohash, pos)                else:                    self.other_torrents.append(infohash)                return        else:            self._get_list(oldstate).remove(infohash)        t.state = newstate        l.insert(pos, infohash)        self._check_queue()  # sends state if it starts the torrent from queue        if t.state != RUNNING or newstate == RUN_QUEUED:            self._send_state(infohash)        self._dump_state()    def set_zero_running_torrents(self):        newrun = []        for infohash in list(self.running_torrents):            t = self.torrents[infohash]            if self._stop_running(infohash):                newrun.append(infohash)                t.state = RUN_QUEUED            else:                self.other_torrents.append(infohash)        self.running_torrents = newrun    def check_completion(self, infohash, filelist=False):        t = self.torrents.get(infohash)        if t is None:            return        r = self.multitorrent.get_completion(self.config, t.metainfo,                                             t.dlpath, filelist)        if r is None or not filelist:            self.run_ui_task(self.ui.update_completion, infohash, r)        else:            self.run_ui_task(self.ui.update_completion, infohash, *r)    def global_error(self, level, text):        self.run_ui_task(self.ui.global_error, level, text)    # callbacks from torrent instances    def failed(self, torrent, is_external):        infohash = torrent.infohash        if infohash == self.starting_torrent:            self.starting_torrent = None        self.running_torrents.remove(infohash)        t = self.torrents[infohash]        t.state = KNOWN        if is_external:            t.completion = self.multitorrent.get_completion(                self.config, t.metainfo, t.dlpath)        else:            t.completion = None        totals = t.dl.get_total_transfer()        t.uptotal_old += totals[0]        t.uptotal = t.uptotal_old        t.downtotal_old += totals[1]        t.downtotal = t.downtotal_old        t.dl = None        self.other_torrents.append(infohash)        self._send_state(infohash)        if not self.doneflag.isSet():            self._check_queue()            self._dump_state()    def finished(self, torrent):        infohash = torrent.infohash        if infohash == self.starting_torrent:            t = self.torrents[infohash]            if self.queue:                ratio = self.config['next_torrent_ratio'] / 100            else:                ratio = self.config['last_torrent_ratio'] / 100            if ratio and t.uptotal >= t.downtotal * ratio:                raise BTShutdown("Not starting torrent as it already meets "                               "the current settings for when to stop seeding")        self.torrents[torrent.infohash].finishtime = bttime()    def started(self, torrent):        infohash = torrent.infohash        assert infohash == self.starting_torrent        self.starting_torrent = None        self._check_queue()    def error(self, torrent, level, text):        self.run_ui_task(self.ui.error, torrent.infohash, level, text)class ThreadWrappedQueue(object):    def __init__(self, wrapped):        self.wrapped = wrapped    def set_done(self):        self.wrapped.doneflag.set()        # add a dummy task to make sure the thread wakes up and notices flag        def dummy():            pass        self.wrapped.rawserver.external_add_task(dummy, 0)def _makemethod(methodname):    def wrapper(self, *args, **kws):        def f():            getattr(self.wrapped, methodname)(*args, **kws)        self.wrapped.rawserver.external_add_task(f, 0)    return wrapperfor methodname in "request_status set_config start_new_torrent remove_torrent set_save_location change_torrent_state check_completion".split():    setattr(ThreadWrappedQueue, methodname, _makemethod(methodname))del _makemethod, methodname

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -