[CalendarServer-changes] [2470] CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/ twistedcaldav/directory

source_changes at macosforge.org source_changes at macosforge.org
Fri May 23 16:52:27 PDT 2008


Revision: 2470
          http://trac.macosforge.org/projects/calendarserver/changeset/2470
Author:   cdaboo at apple.com
Date:     2008-05-23 16:52:26 -0700 (Fri, 23 May 2008)

Log Message:
-----------
Cache the proxy db data. Note that this only works for a single instance server as cache
invalidation is not signaled to other processes.

Modified Paths:
--------------
    CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/calendaruserproxy.py
    CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/test/test_proxyprincipaldb.py

Modified: CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/calendaruserproxy.py
===================================================================
--- CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/calendaruserproxy.py	2008-05-23 23:52:14 UTC (rev 2469)
+++ CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/calendaruserproxy.py	2008-05-23 23:52:26 UTC (rev 2470)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+import itertools
 
 """
 Implements a calendar user proxy principal.
@@ -317,9 +318,15 @@
     dbFilename = db_prefix + "calendaruserproxy"
     dbFormatVersion = "4"
 
+    dbUseCache = True
+
     def __init__(self, path):
         path = os.path.join(path, CalendarUserProxyDatabase.dbFilename)
         super(CalendarUserProxyDatabase, self).__init__(path, True)
+        
+        if self.dbUseCache:
+            self._cacheMembers = {}
+            self._cacheMemberships = {}
 
     def setGroupMembers(self, principalUID, members):
         """
@@ -333,34 +340,87 @@
         self._delete_from_db(principalUID)
         self._add_to_db(principalUID, members)
         self._db_commit()
+        
+        # Update cache if present
+        if self.dbUseCache:
+            try:
+                current_members = set(self._cacheMembers.setdefault(principalUID, []))
+                update_members = set(members)
+                
+                remove_members = current_members.difference(update_members)
+                add_members = update_members.difference(current_members)
+                for member in itertools.chain(remove_members, add_members,):
+                    try:
+                        del self._cacheMemberships[member]
+                    except KeyError:
+                        pass
+                
+                del self._cacheMembers[principalUID]
 
+            except KeyError:
+                pass
+
     def removeGroup(self, principalUID):
         """
         Remove a group membership record.
 
         @param principalUID: the UID of the group principal to remove.
         """
+
         self._delete_from_db(principalUID)
         self._db_commit()
+        
+        # Update cache if present
+        if self.dbUseCache:
+            try:
+                members = self._cacheMembers[principalUID]
+                for member in members:
+                    try:
+                        del self._cacheMemberships[member]
+                    except KeyError:
+                        pass
+                del self._cacheMembers[principalUID]
+            except KeyError:
+                pass
 
     def getMembers(self, principalUID):
         """
         Return the list of group member UIDs for the specified principal.
         """
-        members = set()
-        for row in self._db_execute("select MEMBER from GROUPS where GROUPNAME = :1", principalUID):
-            members.add(row[0])
-        return members
 
+        def _members():
+            members = set()
+            for row in self._db_execute("select MEMBER from GROUPS where GROUPNAME = :1", principalUID):
+                members.add(row[0])
+            return members
+
+        # Pull from cache if present
+        if self.dbUseCache:
+            if not self._cacheMembers.has_key(principalUID):
+                self._cacheMembers[principalUID] = _members()
+            return self._cacheMembers[principalUID]
+        else:
+            return _members()
+
     def getMemberships(self, principalUID):
         """
         Return the list of group principal UIDs the specified principal is a member of.
         """
-        members = set()
-        for row in self._db_execute("select GROUPNAME from GROUPS where MEMBER = :1", principalUID):
-            members.add(row[0])
-        return members
 
+        def _members():
+            members = set()
+            for row in self._db_execute("select GROUPNAME from GROUPS where MEMBER = :1", principalUID):
+                members.add(row[0])
+            return members
+
+        # Pull from cache if present
+        if self.dbUseCache:
+            if not self._cacheMemberships.has_key(principalUID):
+                self._cacheMemberships[principalUID] = _members()
+            return self._cacheMemberships[principalUID]
+        else:
+            return _members()
+
     def _add_to_db(self, principalUID, members):
         """
         Insert the specified entry into the database.

Modified: CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/test/test_proxyprincipaldb.py
===================================================================
--- CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/test/test_proxyprincipaldb.py	2008-05-23 23:52:14 UTC (rev 2469)
+++ CalendarServer/branches/users/cdaboo/proxy-db-cached-2451/twistedcaldav/directory/test/test_proxyprincipaldb.py	2008-05-23 23:52:26 UTC (rev 2470)
@@ -67,9 +67,6 @@
             return "51"
             
     def test_normalDB(self):
-        """
-        DirectoryPrincipalResource.groupMembers()
-        """
     
         # Get the DB
         db_path = self.mktemp()
@@ -80,9 +77,6 @@
         self.assertEqual(db.getMemberships("B"), set(("A",)))
 
     def test_DBIndexed(self):
-        """
-        DirectoryPrincipalResource.groupMembers()
-        """
     
         # Get the DB
         db_path = self.mktemp()
@@ -91,9 +85,6 @@
         self.assertEqual(set([row[1] for row in db._db_execute("PRAGMA index_list(GROUPS)")]), set(("GROUPNAMES", "MEMBERS")))
 
     def test_OldDB(self):
-        """
-        DirectoryPrincipalResource.groupMembers()
-        """
     
         # Get the DB
         db_path = self.mktemp()
@@ -102,9 +93,6 @@
         self.assertEqual(set([row[1] for row in db._db_execute("PRAGMA index_list(GROUPS)")]), set())
 
     def test_DBUpgrade(self):
-        """
-        DirectoryPrincipalResource.groupMembers()
-        """
     
         # Get the DB
         db_path = self.mktemp()
@@ -125,9 +113,6 @@
         db = None
 
     def test_DBUpgradeNewer(self):
-        """
-        DirectoryPrincipalResource.groupMembers()
-        """
     
         # Get the DB
         db_path = self.mktemp()
@@ -148,9 +133,6 @@
         db = None
 
     def test_DBNoUpgradeNewer(self):
-        """
-        DirectoryPrincipalResource.groupMembers()
-        """
     
         # Get the DB
         db_path = self.mktemp()
@@ -170,4 +152,50 @@
         db._db_close()
         db = None
 
+    def test_cachingDBInsert(self):
+    
+        # Get the DB
+        db_path = self.mktemp()
+        os.mkdir(db_path)
+        db = CalendarUserProxyDatabase(db_path)
+        
+        # Do one insert and check the result
+        db.setGroupMembers("A", ("B", "C", "D",))
+        self.assertEqual(db.getMembers("A"), set(("B", "C", "D",)))
+        self.assertEqual(db.getMemberships("B"), set(("A",)))
+        self.assertEqual(db.getMemberships("C"), set(("A",)))
+        self.assertEqual(db.getMemberships("D"), set(("A",)))
+        self.assertEqual(db.getMemberships("E"), set(()))
+        
+        # Change and check the result
+        db.setGroupMembers("A", ("B", "C", "E",))
+        self.assertEqual(db.getMembers("A"), set(("B", "C", "E",)))
+        self.assertEqual(db.getMemberships("B"), set(("A",)))
+        self.assertEqual(db.getMemberships("C"), set(("A",)))
+        self.assertEqual(db.getMemberships("D"), set())
+        self.assertEqual(db.getMemberships("E"), set(("A",)))
+
+    def test_cachingDBRemove(self):
+    
+        # Get the DB
+        db_path = self.mktemp()
+        os.mkdir(db_path)
+        db = CalendarUserProxyDatabase(db_path)
+        
+        # Do one insert and check the result
+        db.setGroupMembers("A", ("B", "C", "D",))
+        db.setGroupMembers("X", ("B", "C",))
+        self.assertEqual(db.getMembers("A"), set(("B", "C", "D",)))
+        self.assertEqual(db.getMembers("X"), set(("B", "C",)))
+        self.assertEqual(db.getMemberships("B"), set(("A", "X",)))
+        self.assertEqual(db.getMemberships("C"), set(("A", "X",)))
+        self.assertEqual(db.getMemberships("D"), set(("A",)))
+        
+        # Remove and check the result
+        db.removeGroup("A")
+        self.assertEqual(db.getMembers("A"), set())
+        db.setGroupMembers("X", ("B", "C",))
+        self.assertEqual(db.getMemberships("B"), set("X",))
+        self.assertEqual(db.getMemberships("C"), set("X",))
+        self.assertEqual(db.getMemberships("D"), set())
         
\ No newline at end of file

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080523/1119b654/attachment-0001.htm 


More information about the calendarserver-changes mailing list