[CalendarServer-changes] [3690] CalendarServer/trunk/twistedcaldav/directory

source_changes at macosforge.org source_changes at macosforge.org
Thu Feb 19 12:50:04 PST 2009


Revision: 3690
          http://trac.macosforge.org/projects/calendarserver/changeset/3690
Author:   cdaboo at apple.com
Date:     2009-02-19 12:50:04 -0800 (Thu, 19 Feb 2009)
Log Message:
-----------
Do not disable entire records when there are short name duplications.

Modified Paths:
--------------
    CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py

Modified: CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py	2009-02-19 20:45:31 UTC (rev 3689)
+++ CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py	2009-02-19 20:50:04 UTC (rev 3690)
@@ -473,7 +473,7 @@
             if isinstance(recordShortNames, str):
                 recordShortNames = (recordShortNames,)
             else:
-                recordShortNames = tuple(recordShortNames) if recordShortNames else ()
+                recordShortNames = tuple(set(recordShortNames)) if recordShortNames else ()
             recordFullName     = value.get(dsattributes.kDS1AttrDistinguishedName)
             recordFirstName    = value.get(dsattributes.kDS1AttrFirstName)
             recordLastName     = value.get(dsattributes.kDS1AttrLastName)
@@ -578,53 +578,51 @@
                 readOnlyProxyGUIDs    = readOnlyProxyGUIDs,
             )
 
-            def disableRecord(record):
-                self.log_warn("Record disabled due to conflict (record name and GUID must match): %s" % (record,))
+            def disableGUID(guid, record):
+                """
+                Disable the record by removing it from all indexes.
+                """
 
-                shortNames = record.shortNames
-                guid       = record.guid
+                self.log_warn("GUID %s disabled due to conflict for record: %s"
+                              % (guid, record))
 
-                disabledNames.update(shortNames)
                 disabledGUIDs.add(guid)
+                disabledNames.update(record.shortNames)
+                disabledEmails.update(record.emailAddresses)
 
-                for shortName in shortNames:
-                    if shortName in records:
+                if guid in guids:
+                    try:
+                        del guids[guid]
+                    except KeyError:
+                        pass
+                for shortName in record.shortNames:
+                    try:
                         del records[shortName]
-                if guid in guids:
-                    del guids[guid]
+                    except KeyError:
+                        pass
+                for email in record.emailAddresses:
+                    try:
+                        del emails[email]
+                    except KeyError:
+                        pass
 
-            # Check for disabled items
-            if disabledNames.intersection(record.shortNames) or record.guid in disabledGUIDs:
-                disableRecord(record)
+            if record.guid in disabledGUIDs:
+                disableGUID(record.guid, record)
             else:
-                # Check for duplicate items and disable all names/guids for mismatched duplicates.
-                existing_records = set()
-                for shortName in record.shortNames:
-                    if shortName in records:
-                        existing_records.add(records[shortName])
-                if record.guid in guids:
-                    existing_records.add(guids[record.guid])
-
-                if existing_records:
-                    disable = False
-                    for existing_record in existing_records:
-                        if record.guid != existing_record.guid or record.shortNames != existing_record.shortNames:
-                            disable = True
-                            break
-                        
-                    if disable:
-                        for existing_record in existing_records:
-                            disableRecord(existing_record)
-                            if existing_record.enabledForCalendaring:
-                                enabled_count -= 1
-                        disableRecord(record)
-
-                if len(disabledNames.intersection(record.shortNames)) == 0:
+                # Check for duplicates
+                existing_record = guids.get(record.guid)
+                if existing_record is not None:
+                    if existing_record.shortNames != record.shortNames:
+                        disableGUID(record.guid, record)
+                        disableGUID(record.guid, existing_record)
+                        if existing_record.enabledForCalendaring:
+                            enabled_count -= 1
+                else:
                     guids[record.guid] = record
-                    for shortName in record.shortNames:
-                        records[shortName] = record
                     self.log_debug("Added record %s to OD record cache" % (record,))
-
+                    if record.enabledForCalendaring:
+                        enabled_count += 1
+        
                     # Do group indexing if needed
                     if recordType == self.recordType_groups:
                         self._indexGroup(record, record._memberGUIDs, groupsForGUID)
@@ -634,28 +632,52 @@
                         self._indexGroup(record, record._proxyGUIDs, proxiesForGUID)
                         self._indexGroup(record, record._readOnlyProxyGUIDs, readOnlyProxiesForGUID)
 
-            def disableEmail(emailAddress, record):
-                self.log_warn("Email address %s disabled due to conflict for record: %s"
-                              % (emailAddress, record))
+                    # Index non-duplicate shortNames
+                    def disableName(shortName, record):
+                        self.log_warn("Short name %s disabled due to conflict for record: %s"
+                                      % (shortName, record))
+        
+                        record.shortNames = tuple([item for item in record.shortNames if item != shortName])
+                        disabledNames.add(shortName)
+        
+                        if shortName in records:
+                            del records[shortName]
+        
+                    for shortName in tuple(record.shortNames):
+                        if shortName in disabledNames:
+                            disableName(shortName, record)
+                        else:
+                            # Check for duplicates
+                            existing_record = records.get(shortName)
+                            if existing_record is not None and existing_record != record:
+                                disableName(shortName, record)
+                                disableName(shortName, existing_record)
+                            else:
+                                records[shortName] = record
+        
+                    # Index non-duplicate emails
+                    def disableEmail(emailAddress, record):
+                        self.log_warn("Email address %s disabled due to conflict for record: %s"
+                                      % (emailAddress, record))
+        
+                        record.emailAddresses.remove(emailAddress)
+                        disabledEmails.add(emailAddress)
+        
+                        if emailAddress in emails:
+                            del emails[emailAddress]
+        
+                    for email in frozenset(recordEmailAddresses):
+                        if email in disabledEmails:
+                            disableEmail(email, record)
+                        else:
+                            # Check for duplicates
+                            existing_record = emails.get(email)
+                            if existing_record is not None:
+                                disableEmail(email, record)
+                                disableEmail(email, existing_record)
+                            else:
+                                emails[email] = record
 
-                record.emailAddresses.remove(emailAddress)
-                disabledEmails.add(emailAddress)
-
-                if emailAddress in emails:
-                    del emails[emailAddress]
-
-            for email in frozenset(recordEmailAddresses):
-                if email in disabledEmails:
-                    disableEmail(email, record)
-                else:
-                    # Check for duplicates
-                    existing_record = emails.get(email)
-                    if existing_record is not None:
-                        disableEmail(email, record)
-                        disableEmail(email, existing_record)
-                    else:
-                        emails[email] = record
-
         if lookup is None:
             #
             # Replace the entire cache

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py	2009-02-19 20:45:31 UTC (rev 3689)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py	2009-02-19 20:50:04 UTC (rev 3690)
@@ -67,9 +67,9 @@
                     self.service.fakerecords[recordType] = []
                 self.service.reloadCache(recordType)
 
-        def verifyRecords(self, recordType, expected):
+        def verifyRecords(self, recordType, expected, key="records"):
             expected = set(expected)
-            found = set(self.service._records[recordType]["records"].keys())
+            found = set(self.service._records[recordType][key].keys())
             
             missing = expected.difference(found)
             extras = found.difference(expected)
@@ -102,6 +102,19 @@
             check("disabled names", expectedNames)
             check("disabled guids", (guid.lower() for guid in expectedGUIDs))
 
+        def verifyDisabledNames(self, recordType, expectedNames):
+            def check(disabledType, expected):
+                expected = set(expected)
+                found = self.service._records[recordType][disabledType]
+            
+                missing = expected.difference(found)
+                extras = found.difference(expected)
+
+                self.assertTrue(len(missing) == 0, msg="Disabled directory records not found: %s" % (missing,))
+                self.assertTrue(len(extras) == 0, msg="Disabled directory records not expected: %s" % (extras,))
+
+            check("disabled names", expectedNames)
+
         def verifyQuery(self, f, *args):
             try:
                 delattr(self.service, "_didQuery")
@@ -315,10 +328,18 @@
             })
 
             self.verifyRecords(DirectoryService.recordType_users, ("user01",))
-            self.verifyDisabledRecords(
+            self.verifyRecords(
                 DirectoryService.recordType_users,
+                (
+                    guidForShortName("user01"),
+                    "A25775BB-1281-4606-98C6-2893B2D5CCD7".lower(),
+                    "30CA2BB9-C935-4A5D-80E2-79266BCB0255".lower(),
+                ),
+                key="guids",
+            )
+            self.verifyDisabledNames(
+                DirectoryService.recordType_users,
                 ("user02",),
-                ("A25775BB-1281-4606-98C6-2893B2D5CCD7", "30CA2BB9-C935-4A5D-80E2-79266BCB0255"),
             )
 
         def test_duplicateGUID(self):
@@ -351,7 +372,7 @@
             self.verifyDisabledRecords(
                 DirectoryService.recordType_users,
                 ("user02", "user03"),
-                ("113D7F74-F84A-4F17-8C96-CE8F10D68EF8", "136E369F-DB40-4135-878D-B75D38242D39"),
+                ("113D7F74-F84A-4F17-8C96-CE8F10D68EF8",),
             )
 
         def test_duplicateGUIDCacheMiss(self):
@@ -383,7 +404,7 @@
             self.verifyDisabledRecords(
                 DirectoryService.recordType_users,
                 ("user02", "user03", "user04", "user05"),
-                ("EDB9EE55-31F2-4EA9-B5FB-D8AE2A8BA35E", "62368DDF-0C62-4C97-9A58-DE9FD46131A0", "D10F3EE0-5014-41D3-8488-3819D3EF3B2A"),
+                ("EDB9EE55-31F2-4EA9-B5FB-D8AE2A8BA35E", "62368DDF-0C62-4C97-9A58-DE9FD46131A0",),
             )
 
         def test_groupmembers(self):
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090219/7c8ed0cb/attachment-0001.html>


More information about the calendarserver-changes mailing list