Contact: fumanchu@aminus.org

Log in as guest/dejavu to create tickets

Changeset 567

Show
Ignore:
Timestamp:
11/02/07 12:58:42
Author:
fumanchu
Message:

Work in progress.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/crazycache/dejavu/storage/caching.py

    r554 r567  
    55from dejavu import logic, logflags, recur 
    66from dejavu.storage import ProxyStorage, resolve 
     7 
     8 
     9simple_attr_lookup = logic.Expression(lambda x: x.Thing == 4).func.func_code.co_code 
    710 
    811 
     
    4346        self.fullquery = allOptions.get("fullquery", False) 
    4447        self.fulljoin = allOptions.get("fulljoin", False) 
     48        self.cache_recalls = [] 
     49        self.xspecial_stride = 50 
    4550         
    4651        self.cache = allOptions.get("cache") 
     
    6873         
    6974        return u 
     75     
     76    def xspecial(self, cls, key, value, order=None): 
     77        """Yield multiple units of the given cls where key=value.""" 
     78        keyattrs = self.cache._keyattrs[cls] 
     79         
     80        # Get a cached list of identifier-tuples, ordered if requested. 
     81        # TODO: add order to the idkey. 
     82        ids = self.cache.get_index(cls, key, value) 
     83        if ids is None: 
     84            # Not in the cache. Grab the list of id-tuples from nextstore. 
     85            ids = self.view((cls, keyattrs, {key: value}), order=order) 
     86            # Then cache the list result for next time. 
     87            self.cache.put_index(cls, key, value, ids, time = 5 * 60) 
     88         
     89        # Query the cache for multiple units (by id). 
     90        items = self.cache.scan_index(cls, ids) 
     91        misses = [k for k in ids if k not in items] 
     92         
     93        # Now query the DB for any items that the cache missed... 
     94        if self.xspecial_stride: 
     95            # ...in chunks of length: self.xspecial_stride. 
     96            for step in xrange(0, len(misses), self.xspecial_stride): 
     97                # TODO: allow for multiple identifiers 
     98                f = lambda x: ((getattr(x, keyattrs[0]), ) in 
     99                               misses[step:step + self.xspecial_stride]) 
     100                for unit in self.recall(cls, f): 
     101                    items[tuple([getattr(unit, a) for a in keyattrs])] = unit 
     102        elif misses: 
     103            # ...or all in one chunk if desired. 
     104            f = lambda x: (getattr(x, keyattrs[0]), ) in misses 
     105            for unit in self.recall(cls, f): 
     106                items[tuple([getattr(unit, a) for a in keyattrs])] = unit 
     107         
     108        # Return non-null items only, preserving order 
     109        for k in ids: 
     110            yield items[k] 
     111##            unit = items[k] 
     112##            if unit is not None: 
     113##                yield unit 
    70114     
    71115    def xrecall(self, classes, expr=None, order=None, limit=None, offset=None): 
     
    101145        elif offset: 
    102146            raise TypeError("Order argument expected when offset is provided.") 
    103         elif self.fullquery and cls.identifiers and cls in self.cache.classes: 
    104             # Query the cache. 
    105             for unit in self.cache.xrecall(cls, expr, limit=limit, offset=offset): 
    106                 seen[unit.identity()] = None 
    107                 yield unit 
    108             limit = limit - len(keys) 
     147        elif cls.identifiers and cls in self.cache.classes: 
     148            fc = expr.func.func_code 
     149            compkeys = fc.co_names[1:] 
     150            if (fc.co_code == simple_attr_lookup and len(compkeys) == 1 
     151##                and (cls, compkeys[0]) in self.cache_recalls 
     152                ): 
     153                for unit in self.xspecial(cls, compkeys[0], fc.co_consts[1], order): 
     154                    yield unit 
     155            elif self.fullquery: 
     156                # Query the cache. 
     157                for unit in self.cache.xrecall(cls, expr, limit=limit, offset=offset): 
     158                    seen[unit.identity()] = None 
     159                    yield unit 
     160                limit = limit - len(keys) 
    109161         
    110162        # Query storage. 
  • branches/crazycache/dejavu/storage/storememcached.py

    r565 r567  
    387387        # else: 
    388388        #     self.increment_generation(cls) 
    389  
     389     
     390    def get_index(self, cls, key, value): 
     391        """Return a cached list of unit identifiers where unit.key == value. 
     392         
     393        The ids returned will be a list of tuples of the form: 
     394            tuple([getattr(unit, name) for name in self._keyattrs[cls]]) 
     395         
     396        In general, callers should use get_index, put_index, and scan_index 
     397        together: 
     398             
     399            ids = get_index(cls, ...) 
     400            if ids is None: 
     401                ids = expensive_lookup(cls, ...) 
     402                put_index(cls, ...) 
     403            items = scan_index(cls, ids) 
     404            misses = [k for k in ids if k not in items] 
     405        """ 
     406        if self.logflags & logflags.IO: 
     407            self.log(logflags.IO.message("INDEX GET %s (%r == %r)" % 
     408                                         (cls.__name__, key, value))) 
     409        cachekey = '%s:%s:ids(%s:%s)' % (self.name, cls.__name__, key, value) 
     410        return self.client.get(cachekey) 
     411     
     412    def put_index(self, cls, key, value, ids, time=None): 
     413        """Cache a list of unit identifiers where unit.key == value. 
     414         
     415        The ids provided MUST be a list of tuples of the form: 
     416            tuple([getattr(unit, name) for name in self._keyattrs[cls]]) 
     417        """ 
     418        if self.logflags & logflags.IO: 
     419            self.log(logflags.IO.message("INDEX PUT %s (%r == %r)" % 
     420                                         (cls.__name__, key, value))) 
     421        cachekey = '%s:%s:ids(%s:%s)' % (self.name, cls.__name__, key, value) 
     422        self.client.set(cachekey, ids, time=time) 
     423     
     424    def scan_index(self, cls, ids): 
     425        """Yield multiple units from the given set of ids. 
     426         
     427        The ids provided MUST be a list of tuples of the form: 
     428            tuple([getattr(unit, name) for name in self._keyattrs[cls]]) 
     429        """ 
     430        if self.logflags & logflags.IO: 
     431            self.log(logflags.IO.message("INDEX SCAN %s" % cls.__name__)) 
     432        clsname = cls.__name__ 
     433        keys = ["%s:%s:%s" % (self.name, clsname, self.hash(i)) for i in ids] 
     434        return self.client.get_multi(keys) 
     435 
  • branches/crazycache/dejavu/test/zoo_fixture.py

    r561 r567  
    16301630            tools.djvTestRunner.run(loader(KeyStoreTests)) 
    16311631            tools.djvTestRunner.run(loader(NumericTests)) 
    1632             tools.djvTestRunner.run(loader(ConcurrencyTests)) 
     1632##            tools.djvTestRunner.run(loader(ConcurrencyTests)) 
    16331633            tools.djvTestRunner.run(loader(DiscoveryTests)) 
    16341634        except: