Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

Changeset 906

Show
Ignore:
Timestamp:
12/31/05 23:29:26
Author:
fumanchu
Message:

Fix for #425. See the ticket comments for lots of details.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/cherrypy/filters/cachefilter.py

    r902 r906  
    77import basefilter 
    88 
    9 def defaultCacheKey(): 
    10     return cherrypy.request.browser_url 
    11  
    129 
    1310class MemoryCache: 
    14  
    15     def __init__(self, key, delay, maxobjsize, maxsize, maxobjects): 
    16         self.key = key 
    17         self.delay = delay 
    18         self.maxobjsize = maxobjsize 
    19         self.maxsize = maxsize 
    20         self.maxobjects = maxobjects 
    21         self.cursize = 0 
     11     
     12    def __init__(self): 
     13        self.clear() 
     14        self.expirationQueue = Queue.Queue() 
     15        t = self.expirationThread = threading.Thread(target=self.expireCache, 
     16                                                     name='expireCache') 
     17        t.setDaemon(True) 
     18        t.start() 
     19     
     20    def clear(self): 
     21        """Reset the cache to its initial, empty state.""" 
    2222        self.cache = {} 
    23         self.expirationQueue = Queue.Queue() 
    24         self.expirationThread = threading.Thread(target=self.expireCache, name='expireCache') 
    25         self.expirationThread.setDaemon(True) 
    26         self.expirationThread.start() 
    27         self.totPuts = 0 
    28         self.totGets = 0 
    29         self.totHits = 0 
    30         self.totExpires = 0 
    31         self.totNonModified = 0 
    32  
    33     def clear(self): 
    34         """Simply reset the cache to its initial state, all cleared of its values""" 
    35         self.cache.clear() 
    3623        self.totPuts = 0 
    3724        self.totGets = 0 
     
    4027        self.totNonModified = 0 
    4128        self.cursize = 0 
    42  
     29     
     30    def _key(self): 
     31        return cherrypy.config.get("cache_filter.key", cherrypy.request.browser_url) 
     32    key = property(_key) 
     33     
     34    def _maxobjsize(self): 
     35        return cherrypy.config.get("cache_filter.maxobjsize", 100000) 
     36    maxobjsize = property(_maxobjsize) 
     37     
     38    def _maxsize(self): 
     39        return cherrypy.config.get("cache_filter.maxsize", 10000000) 
     40    maxsize = property(_maxsize) 
     41     
     42    def _maxobjects(self): 
     43        return cherrypy.config.get("cache_filter.maxobjects", 1000) 
     44    maxobjects = property(_maxobjects) 
     45     
    4346    def expireCache(self): 
    4447        while True: 
     
    5760                # the key may have been deleted elsewhere 
    5861                pass 
    59  
     62     
    6063    def get(self): 
    6164        """ 
     
    6568        """ 
    6669        self.totGets += 1 
    67         cacheItem = self.cache.get(self.key(), None) 
     70        cacheItem = self.cache.get(self.key, None) 
    6871        if cacheItem: 
    6972            self.totHits += 1 
     
    7174        else: 
    7275            return None 
    73          
     76     
    7477    def put(self, lastModified, obj): 
    7578        # Size check no longer includes header length 
    7679        objSize = len(obj[2]) 
    7780        totalSize = self.cursize + objSize 
     81         
    7882        # checks if there's space for the object 
    7983        if ((objSize < self.maxobjsize) and  
     
    8286            # add to the expirationQueue & cache 
    8387            try: 
    84                 expirationTime = time.time() + self.delay 
    85                 objKey = self.key() 
     88                expirationTime = time.time() + cherrypy.config.get("cache_filter.delay", 600) 
     89                objKey = self.key 
    8690                self.expirationQueue.put((expirationTime, objSize, objKey)) 
     91                self.cache[objKey] = (expirationTime, lastModified, obj) 
    8792                self.totPuts += 1 
    8893                self.cursize += objSize 
     
    9095                # can't add because the queue is full 
    9196                return 
    92             self.cache[objKey] = (expirationTime, lastModified, obj) 
    9397 
    9498 
     
    98102    """ 
    99103     
    100     CacheClass = property(lambda self: cherrypy.config.get("cache_filter.cacheClass", MemoryCache)) 
    101     key = property(lambda self: cherrypy.config.get("cache_filter.key", defaultCacheKey)
    102     delay = property(lambda self: cherrypy.config.get("cache_filter.delay", 600)
    103     maxobjsize = property(lambda self: cherrypy.config.get("cache_filter.maxobjsize", 100000)) 
    104     maxsize = property(lambda self: cherrypy.config.get("cache_filter.maxsize", 10000000)) 
    105     maxobjects = property(lambda self: cherrypy.config.get("cache_filter.maxobjects", 1000)) 
     104    def __init__(self): 
     105        cache_class = cherrypy.config.get("cache_filter.cacheClass", MemoryCache
     106        cherrypy._cache = cache_class(
     107     
     108    def on_start_resource(self): 
     109        cherrypy.request.cacheable = False 
    106110     
    107111    def before_main(self): 
     
    109113            return 
    110114         
    111         if not hasattr(cherrypy, '_cache'): 
    112             cherrypy._cache = self.CacheClass(self.key, self.delay, 
    113                 self.maxobjsize, self.maxsize, self.maxobjects) 
    114          
    115         if hasattr(cherrypy, '_clear_cache') and cherrypy._clear_cache == True: 
    116             cherrypy._cache.clear() 
    117          
    118115        cacheData = cherrypy._cache.get() 
    119         cherrypy.request.cacheable = not cacheData 
    120116        if cacheData: 
    121117            # found a hit! check the if-modified-since request header 
     
    128124            else: 
    129125                # serve it & get out from the request 
    130                 cherrypy.response.status, cherrypy.response.headers, body = obj 
     126                cherrypy.response.status, cherrypy.response.header_list, body = obj 
    131127                cherrypy.response.body = body 
    132128            raise cherrypy.RequestHandled() 
     129        else: 
     130            cherrypy.request.cacheable = True 
    133131     
    134132    def before_finalize(self): 
    135         if not (cherrypy.config.get('cache_filter.on', False) and 
    136                 cherrypy.request.cacheable): 
     133        if not cherrypy.request.cacheable: 
    137134            return 
    138135         
     
    147144    def on_end_request(self): 
    148145        # Close & fix the cache entry after content was fully written 
    149         if not (cherrypy.config.get('cache_filter.on', False) and 
    150                 cherrypy.request.cacheable): 
     146        if not cherrypy.request.cacheable: 
    151147            return 
    152148         
    153149        response = cherrypy.response 
    154         status = response.status 
    155         headers = response.headers 
    156         body = ''.join([chunk for chunk in response._cachefilter_tee]) 
    157          
    158150        if response.headers.get('Pragma', None) != 'no-cache': 
    159151            lastModified = response.headers.get('Last-Modified', None) 
    160             # saves the cache data 
    161             cherrypy._cache.put(lastModified, (status, headers, body)) 
     152            # save the cache data 
     153            body = ''.join([chunk for chunk in response._cachefilter_tee]) 
     154            cherrypy._cache.put(lastModified, (response.status, 
     155                                               response.header_list, 
     156                                               body)) 
    162157 
    163158 
  • trunk/cherrypy/test/test_cache_filter.py

    r902 r906  
    1111     
    1212    def index(self): 
    13         counter = cherrypy.counter +
    14         cherrypy.counter = counter 
    15         return "visit #%s" % counter 
     13        cherrypy.counter +=
     14        msg = "visit #%s" % cherrypy.counter 
     15        return msg 
    1616    index.exposed = True 
    1717 
     
    2929     
    3030    def testCaching(self): 
    31         # force the cache to be cleared between different tests 
    32         cherrypy._clear_cache = True 
    3331        for trial in xrange(10): 
    34             trial = trial + 1 
    3532            self.getPage("/") 
    36             self.assertBody('visit #%d' % trial) 
     33            # The response should be the same every time! 
     34            self.assertBody('visit #1') 
    3735 
    3836if __name__ == '__main__': 
    3937    helper.testmain() 
     38 

Hosted by WebFaction

Log in as guest/cpguest to create tickets