[CalendarServer-changes] [2405] CalendarServer/branches/propfind-cache-3/twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Fri May 9 14:20:43 PDT 2008


Revision: 2405
          http://trac.macosforge.org/projects/calendarserver/changeset/2405
Author:   dreid at apple.com
Date:     2008-05-09 14:20:42 -0700 (Fri, 09 May 2008)

Log Message:
-----------
Use an LRU cache expiration algorithm.

Modified Paths:
--------------
    CalendarServer/branches/propfind-cache-3/twistedcaldav/cache.py
    CalendarServer/branches/propfind-cache-3/twistedcaldav/config.py
    CalendarServer/branches/propfind-cache-3/twistedcaldav/root.py
    CalendarServer/branches/propfind-cache-3/twistedcaldav/test/test_cache.py

Modified: CalendarServer/branches/propfind-cache-3/twistedcaldav/cache.py
===================================================================
--- CalendarServer/branches/propfind-cache-3/twistedcaldav/cache.py	2008-05-09 20:27:50 UTC (rev 2404)
+++ CalendarServer/branches/propfind-cache-3/twistedcaldav/cache.py	2008-05-09 21:20:42 UTC (rev 2405)
@@ -73,16 +73,19 @@
          response) values.
     """
 
-    CACHE_TIMEOUT = 60*60 #1hr
+    CACHE_SIZE = 1000
     propertyStoreFactory = xattrPropertyStore
 
-    def __init__(self, docroot, cacheTimeout=None):
+    def __init__(self, docroot, cacheSize=None):
         self._docroot = docroot
         self._responses = {}
-        if cacheTimeout:
-            self.CACHE_TIMEOUT = cacheTimeout
 
+        if cacheSize is not None:
+            self.CACHE_SIZE = cacheSize
 
+        self._accessTimes = None
+
+
     def _tokenForURI(self, uri):
         """
         Get a property store for the given C{uri}.
@@ -155,7 +158,7 @@
                         self._responses.keys(),))
                 return None
 
-            principalToken, uriToken, cacheTime, response = self._responses[key]
+            principalToken, uriToken, accessTime, response = self._responses[key]
 
             if self._tokenForURI(principalURI) != principalToken:
                 self.log_debug("Principal token changed: %r" % (
@@ -167,15 +170,17 @@
                         key,))
                 return None
 
-            elif self._time() >= cacheTime + self.CACHE_TIMEOUT:
-                return None
-
             response[1].removeHeader('date')
 
             responseObj = Response(response[0],
                                    headers=response[1],
                                    stream=MemoryStream(response[2]))
 
+            self._responses[key] = (principalToken,
+                                    uriToken,
+                                    self._time(),
+                                    response)
+
             self.log_debug("Found in cache: %r = %r" % (key,
                                                         responseObj))
 
@@ -223,11 +228,29 @@
             self.log_debug("Adding to cache: %r = %r" % (key,
                                                          response))
 
+            if len(self._responses) >= self.CACHE_SIZE:
+                leastRecentlyUsedTime = None
+                leastRecentlyUsedKey = None
+
+                for cacheKey, cacheEntry in self._responses.iteritems():
+                    if leastRecentlyUsedTime is None:
+                        leastRecentlyUsedTime = cacheEntry[2]
+                        leastRecentlyUsedKey = cacheKey
+                        continue
+
+                    if leastRecentlyUsedTime < cacheEntry[2]:
+                        leastRecentlyUsedTime = cacheEntry[2]
+                        leastRecentlyUsedKey = cacheKey
+
+                del self._responses[leastRecentlyUsedKey]
+
+
             self._responses[key] = (self._tokenForURI(principalURI),
                                     self._tokenForURI(request.uri),
-                                    self._time(), (response.code,
-                                                   response.headers,
-                                                   responseBody))
+                                    self._time(),
+                                    (response.code,
+                                     response.headers,
+                                     responseBody))
 
             self.log_debug("Cache Stats: # keys = %r" % (len(self._responses),))
 

Modified: CalendarServer/branches/propfind-cache-3/twistedcaldav/config.py
===================================================================
--- CalendarServer/branches/propfind-cache-3/twistedcaldav/config.py	2008-05-09 20:27:50 UTC (rev 2404)
+++ CalendarServer/branches/propfind-cache-3/twistedcaldav/config.py	2008-05-09 21:20:42 UTC (rev 2405)
@@ -192,7 +192,7 @@
     "MaxRequests": 600,
 
     # Configure the number of seconds that Propfinds should be cached for.
-    "ResponseCacheTimeout": 60*60, # 1 Hour.
+    "ResponseCacheSize": 1000
 }
 
 class Config (object):

Modified: CalendarServer/branches/propfind-cache-3/twistedcaldav/root.py
===================================================================
--- CalendarServer/branches/propfind-cache-3/twistedcaldav/root.py	2008-05-09 20:27:50 UTC (rev 2404)
+++ CalendarServer/branches/propfind-cache-3/twistedcaldav/root.py	2008-05-09 21:20:42 UTC (rev 2405)
@@ -52,7 +52,7 @@
 
         self.contentFilters = []
 
-        self.responseCache = ResponseCache(self.fp, config.ResponseCacheTimeout)
+        self.responseCache = ResponseCache(self.fp, config.ResponseCacheSize)
 
         if config.ResponseCompression:
             from twisted.web2.filter import gzip

Modified: CalendarServer/branches/propfind-cache-3/twistedcaldav/test/test_cache.py
===================================================================
--- CalendarServer/branches/propfind-cache-3/twistedcaldav/test/test_cache.py	2008-05-09 20:27:50 UTC (rev 2404)
+++ CalendarServer/branches/propfind-cache-3/twistedcaldav/test/test_cache.py	2008-05-09 21:20:42 UTC (rev 2405)
@@ -165,18 +165,6 @@
         return d
 
 
-    def test_getResponseForRequestCacheTimeoutLapsed(self):
-        self.rc._time = (lambda: 50000)
-
-        d = self.rc.getResponseForRequest(StubRequest(
-                'PROPFIND',
-                '/calendars/users/cdaboo/',
-                '/principals/users/cdaboo/'))
-
-        d.addCallback(self.assertEquals, None)
-        return d
-
-
     def test_getResponseForDepthZero(self):
         d = self.rc.getResponseForRequest(StubRequest(
                 'PROPFIND',
@@ -243,3 +231,24 @@
 
         token = rc._tokenForURI('/principals/users/wsanchez')
         self.assertEquals(token, expected_token)
+
+
+    def test_cacheSizeExceeded(self):
+        self.rc.CACHE_SIZE = 1
+        def _assertResponse(ign):
+            d1 = self.rc.getResponseForRequest(StubRequest(
+                    'PROPFIND',
+                    '/calendars/users/cdaboo/',
+                    '/principals/users/cdaboo/'))
+
+            d1.addCallback(self.assertEquals, None)
+            return d1
+
+        d = self.rc.cacheResponseForRequest(
+            StubRequest('PROPFIND',
+                        '/principals/users/dreid/',
+                        '/principals/users/dreid/'),
+            StubResponse(200, {}, "Foobar"))
+
+        d.addCallback(_assertResponse)
+        return d

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080509/7a649e1d/attachment.html


More information about the calendarserver-changes mailing list