Ejemplo n.º 1
0
    def items(self, view=None, prefetch=None, cache=True):
        """ Get list of download items.

            @param view: Name of the view.
            @param prefetch: OPtional list of field names to fetch initially.
            @param cache: Cache items for the given view?
        """
        # TODO: Cache should be by hash.
        # Then get the initial data when cache is empty,
        # else get a list of hashes from the view, make a diff
        # to what's in the cache, fetch the rest. Getting the
        # fields for one hash might be done by a special view
        # (filter: $d.hash == hashvalue)

        if view is None:
            view = engine.TorrentView(self, "default")
        elif isinstance(view, basestring):
            view = engine.TorrentView(self, self._resolve_viewname(view))
        else:
            view.viewname = self._resolve_viewname(view.viewname)

        if not cache or view.viewname not in self._item_cache:
            # Map pyroscope names to rTorrent ones
            if prefetch:
                prefetch = self.CORE_FIELDS | set(
                    (self.PYRO2RT_MAPPING.get(i, i) for i in prefetch))
            else:
                prefetch = self.PREFETCH_FIELDS

            # Fetch items
            items = []
            try:
                # Prepare multi-call arguments
                args = [
                    "d.%s%s" %
                    ("" if field.startswith("is_") else "get_", field)
                    for field in prefetch
                ]

                infohash = view._check_hash_view()
                if infohash:
                    multi_call = self.open().system.multicall
                    args = [
                        dict(methodName=field.rsplit('=', 1)[0],
                             params=[infohash] +
                             (field.rsplit('=', 1)[1].split(',')
                              if '=' in field else [])) for field in args
                    ]
                    raw_items = [[i[0] for i in multi_call(args)]]
                else:
                    multi_call = self.open().d.multicall
                    args = [view.viewname] + [
                        field if '=' in field else field + '='
                        for field in args
                    ]
                    if view.matcher and int(config.fast_query):
                        pre_filter = matching.unquote_pre_filter(
                            view.matcher.pre_filter())
                        self.LOG.info("!!! pre-filter: {}".format(pre_filter
                                                                  or 'N/A'))
                        if pre_filter:
                            multi_call = self.open().d.multicall.filtered
                            args.insert(1, pre_filter)
                    raw_items = multi_call(*tuple(args))

                ##self.LOG.debug("multicall %r" % (args,))
                ##import pprint; self.LOG.debug(pprint.pformat(raw_items))
                self.LOG.debug("Got %d items with %d attributes from %r [%s]" %
                               (len(raw_items), len(prefetch), self.engine_id,
                                multi_call))

                for item in raw_items:
                    items.append(
                        RtorrentItem(
                            self,
                            zip([
                                self.RT2PYRO_MAPPING.get(i, i)
                                for i in prefetch
                            ], item)))
                    yield items[-1]
            except xmlrpc.ERRORS as exc:
                raise error.EngineError(
                    "While getting download items from %r: %s" % (self, exc))

            # Everything yielded, store for next iteration
            if cache:
                self._item_cache[view.viewname] = items
        else:
            # Yield prefetched results
            for item in self._item_cache[view.viewname]:
                yield item
Ejemplo n.º 2
0
    def items(self, view=None, prefetch=None, cache=True):
        """ Get list of download items.
        
            @param view: Name of the view.
            @param prefetch: OPtional list of field names to fetch initially.
            @param cache: Cache items for the given view?
        """
        # TODO: Cache should be by hash.
        # Then get the initial data when cache is empty,
        # else get a list of hashes from the view, make a diff
        # to what's in the cache, fetch the rest. Getting the
        # fields for one hash might be done by a special view
        # (filter: $d.get_hash == hashvalue)

        if view is None:
            view = engine.TorrentView(self, "main")
        elif isinstance(view, basestring):
            view = engine.TorrentView(self, self._resolve_viewname(view))
        else:
            view.viewname = self._resolve_viewname(view.viewname)

        if not cache or view.viewname not in self._item_cache:
            # Map pyroscope names to rTorrent ones
            if prefetch:
                prefetch = self.CORE_FIELDS | set(
                    (self.PYRO2RT_MAPPING.get(i, i) for i in prefetch))
            else:
                prefetch = self.PREFETCH_FIELDS

            # Fetch items
            items = []
            try:
                # Prepare multi-call arguments
                args = [
                    "d.%s%s" %
                    ("" if field.startswith("is_") else "get_", field)
                    for field in prefetch
                ]

                infohash = None
                if view.viewname.startswith('#'):
                    infohash = view.viewname[1:]
                elif len(view.viewname) == 40:
                    try:
                        int(view.viewname, 16)
                    except (TypeError, ValueError):
                        pass
                    else:
                        infohash = view.viewname

                if infohash:
                    multi_call = self.open().system.multicall
                    args = [
                        dict(methodName=field, params=[infohash])
                        for field in args
                    ]
                    raw_items = [[i[0] for i in multi_call(args)]]
                else:
                    multi_call = self.open().d.multicall
                    args = [view.viewname] + [field + '=' for field in args]
                    raw_items = multi_call(*tuple(args))

                ##self.LOG.debug("multicall %r" % (args,))
                ##import pprint; self.LOG.debug(pprint.pformat(raw_items))
                self.LOG.debug("Got %d items with %d attributes from %r [%s]" %
                               (len(raw_items), len(prefetch), self.engine_id,
                                multi_call))

                for item in raw_items:
                    items.append(
                        RtorrentItem(
                            self,
                            zip([
                                self.RT2PYRO_MAPPING.get(i, i)
                                for i in prefetch
                            ], item)))
                    yield items[-1]
            except xmlrpc.ERRORS, exc:
                raise error.EngineError(
                    "While getting download items from %r: %s" % (self, exc))

            # Everything yielded, store for next iteration
            if cache:
                self._item_cache[view.viewname] = items