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

Changeset 1185

Show
Ignore:
Timestamp:
07/06/06 00:04:33
Author:
fumanchu
Message:

caching: Turned MemoryCache?.expirationQueue into "expirations", a dict. This solves some corner cases where a queued object with a long delay would prevent queued objects of shorter delays from expiring on time. It also removes the (variable-period) sleep call buried in Queue, and now uses a single 0.1 sec poll rate.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/cherrypy/lib/caching.py

    r1184 r1185  
    1 import Queue 
    21import threading 
    32import time 
     
    1110    def __init__(self): 
    1211        self.clear() 
    13         self.expirationQueue = Queue.Queue() 
    1412        t = threading.Thread(target=self.expireCache, name='expireCache') 
    1513        self.expirationThread = t 
     
    2018        """Reset the cache to its initial, empty state.""" 
    2119        self.cache = {} 
     20        self.expirations = {} 
    2221        self.totPuts = 0 
    2322        self.totGets = 0 
     
    3130    key = property(_key) 
    3231     
    33     def _maxobjsize(self): 
    34         return cherrypy.request.config.get("tools.caching.maxobjsize", 100000) 
    35     maxobjsize = property(_maxobjsize) 
    36      
    37     def _maxsize(self): 
    38         return cherrypy.request.config.get("tools.caching.maxsize", 10000000) 
    39     maxsize = property(_maxsize) 
    40      
    41     def _maxobjects(self): 
    42         return cherrypy.request.config.get("tools.caching.maxobjects", 1000) 
    43     maxobjects = property(_maxobjects) 
    44      
    4532    def expireCache(self): 
    46         while True: 
    47             expirationTime, objSize, objKey = self.expirationQueue.get(block=True, timeout=None) 
    48             # expireCache runs in a separate thread which the servers are 
    49             # not aware of. It's possible that "time" will be set to None 
    50             # arbitrarily, so we check "while time" to avoid exceptions. 
    51             # See tickets #99 and #180 for more information. 
    52             while time and (time.time() < expirationTime): 
    53                 time.sleep(0.1) 
    54             try: 
    55                 del self.cache[objKey] 
    56                 self.totExpires += 1 
    57                 self.cursize -= objSize 
    58             except KeyError: 
    59                 # the key may have been deleted elsewhere 
    60                 pass 
     33        # expireCache runs in a separate thread which the servers are 
     34        # not aware of. It's possible that "time" will be set to None 
     35        # arbitrarily, so we check "while time" to avoid exceptions. 
     36        # See tickets #99 and #180 for more information. 
     37        while time: 
     38            now = time.time() 
     39            for expirationTime, objects in self.expirations: 
     40                if expirationTime <= now: 
     41                    for objSize, objKey in objects: 
     42                        try: 
     43                            del self.cache[objKey] 
     44                            self.totExpires += 1 
     45                            self.cursize -= objSize 
     46                        except KeyError: 
     47                            # the key may have been deleted elsewhere 
     48                            pass 
     49            time.sleep(0.1) 
    6150     
    6251    def get(self): 
     
    7160     
    7261    def put(self, obj): 
    73         # Size check no longer includes header length 
    74         objSize = len(obj[2]) 
    75         totalSize = self.cursize + objSize 
     62        conf = cherrypy.request.config.get 
    7663         
    77         # checks if there's space for the object 
    78         if ((objSize < self.maxobjsize) and  
    79             (totalSize < self.maxsize) and  
    80             (len(self.cache) < self.maxobjects)): 
    81             # add to the expirationQueue & cache 
    82             try: 
    83                 expirationTime = time.time() + cherrypy.request.config.get("tools.caching.delay", 600) 
     64        if len(self.cache) < conf("tools.caching.maxobjects", 1000): 
     65            # Size check no longer includes header length 
     66            objSize = len(obj[2]) 
     67            maxobjsize = conf("tools.caching.maxobjsize", 100000) 
     68             
     69            totalSize = self.cursize + objSize 
     70            maxsize = conf("tools.caching.maxsize", 10000000) 
     71             
     72            # checks if there's space for the object 
     73            if (objSize < maxobjsize and totalSize < maxsize): 
     74                # add to the expirations list and cache 
     75                expirationTime = time.time() + conf("tools.caching.delay", 600) 
    8476                objKey = self.key 
    85                 self.expirationQueue.put((expirationTime, objSize, objKey)) 
     77                bucket = self.expirations.setdefault(expirationTime, []) 
     78                bucket.append((objSize, objKey)) 
    8679                self.cache[objKey] = obj 
    8780                self.totPuts += 1 
    88                 self.cursize += objSize 
    89             except Queue.Full: 
    90                 # can't add because the queue is full 
    91                 return 
     81                self.cursize = totalSize 
    9282 
    9383 

Hosted by WebFaction

Log in as guest/cpguest to create tickets