[CalendarServer-changes] [11661] CalendarServer/branches/users/gaya/sharedgroupfixes/txdav
source_changes at macosforge.org
source_changes at macosforge.org
Mon Sep 9 15:41:27 PDT 2013
Revision: 11661
http://trac.calendarserver.org//changeset/11661
Author: gaya at apple.com
Date: 2013-09-09 15:41:27 -0700 (Mon, 09 Sep 2013)
Log Message:
-----------
Checkpoint changes
Modified Paths:
--------------
CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/sql.py
CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/test/test_sql.py
CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql.py
CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql_schema/current-oracle-dialect.sql
CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql_schema/current.sql
CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql
CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql
Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/sql.py 2013-09-07 03:09:24 UTC (rev 11660)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/sql.py 2013-09-09 22:41:27 UTC (rev 11661)
@@ -398,7 +398,10 @@
def __init__(self, home, name, resourceID, mode, status, revision=0, message=None, ownerHome=None, bindName=None):
ownerName = ownerHome.addressbook().name() if ownerHome else None
- super(AddressBook, self).__init__(home, name, resourceID, mode, status, revision=revision, message=message, ownerHome=ownerHome, ownerName=ownerName)
+ super(AddressBook, self).__init__(
+ home, name, resourceID, mode, status, revision=revision,
+ message=message, ownerHome=ownerHome, ownerName=ownerName
+ )
self._index = PostgresLegacyABIndexEmulator(self)
self._bindName = bindName
@@ -451,6 +454,32 @@
@inlineCallbacks
+ def resourceNamesSinceRevision(self, revision):
+ """
+ Return the changed and deleted resources since a particular revision. This implementation takes
+ into account sharing by making use of the bindRevision attribute to determine if the requested
+ revision is earlier than the share acceptance. If so, then we need to return all resources in
+ the results since the collection is in effect "new".
+
+ @param revision: the revision to determine changes since
+ @type revision: C{int}
+ """
+
+ print("AddressBook: resourceNamesSinceRevision:%s revision:%s" % (self, revision,))
+ if self.fullyShared():
+ returnValue((yield super(AddressBook, self).resourceNamesSinceRevision(revision)))
+
+ # call sharedChildResourceNamesSinceRevision() and filter results
+ sharedChildChanged, sharedChildDeleted = yield self.sharedChildResourceNamesSinceRevision(revision, "infinity")
+
+ path = self.name() + '/'
+ lenpath = len(path)
+ changed = [item[lenpath:] for item in sharedChildChanged if item.startswith(path) and item != path]
+ deleted = [item[lenpath:] for item in sharedChildDeleted if item.startswith(path) and item != path]
+ returnValue((changed, deleted,))
+
+
+ @inlineCallbacks
def sharedChildResourceNamesSinceRevision(self, revision, depth):
"""
Determine the list of child resources that have changed since the specified sync revision.
@@ -471,6 +500,8 @@
@param depth: depth for determine what changed
@type depth: C{str}
"""
+
+ print("sharedChildResourceNamesSinceRevision:%s revision:%s, depth:%s" % (self, revision, depth))
assert not self.owned()
if self.fullyShared():
@@ -478,53 +509,117 @@
changed = set()
deleted = set()
+
+ groupBindRows = yield AddressBookObject._acceptedBindForHomeIDAndAddressBookID.on(
+ self._txn, homeID=self._home._resourceID, addressbookID=self._resourceID
+ )
+ acceptedGroupIDs = [groupBindRow[2] for groupBindRow in groupBindRows]
+ minRevision = min([groupBindRow[5] for groupBindRow in groupBindRows])
+ sharerevision = 0 if revision < minRevision else revision
+ print("sharedChildResourceNamesSinceRevision:%s minRevision:%s, sharerevision:%s" % (self, minRevision, sharerevision))
+
+ # get revision table changes
rev = self._revisionsSchema
- sharerevision = 0 if revision < self._bindRevision else revision
- results = [
- (
- name if name else "",
+ results = [(
+ name,
wasdeleted,
- changeRevision
- )
- for name, wasdeleted, changeRevision in
- (yield Select([rev.RESOURCE_NAME, rev.RESOURCE_ID, rev.DELETED, rev.REVISION],
+ ) for name, wasdeleted in (
+ yield Select([rev.RESOURCE_NAME, rev.DELETED],
From=rev,
Where=(rev.REVISION > sharerevision).And(
- rev.RESOURCE_ID == self._resourceID)).on(self._txn))
- if name
+ rev.RESOURCE_ID == self._resourceID)).on(self._txn)
+ ) if name
]
+ print("sharedChildResourceNamesSinceRevision:%s results:%s" % (self, results))
+ # get members table changes
aboMembers = schema.ABO_MEMBERS
- memberResults = yield Select(
- [aboMembers.RESOURCE_NAME, aboMembers.MEMBER_ID, aboMembers.REMOVED, aboMembers.REVISION],
- From=rev,
- Where=(rev.REVISION > sharerevision).And(
- aboMembers.ADDRESSBOOK_ID == self._resourceID)
+ memberRows = yield Select(
+ [aboMembers.GROUP_ID, aboMembers.MEMBER_ID, aboMembers.REMOVED],
+ From=aboMembers,
+ Where=(aboMembers.REVISION > sharerevision).And(
+ aboMembers.ADDRESSBOOK_ID == self._resourceID)
).on(self._txn)
+ groupIDToChangedMemberIDMap = {}
+ for groupID, memberID, removed in memberRows:
+ if groupIDToChangedMemberIDMap.get(groupID) is None:
+ groupIDToChangedMemberIDMap[groupID] = set()
+ groupIDToChangedMemberIDMap[groupID].add(memberID)
+ print("sharedChildResourceNamesSinceRevision:%s memberRows:%s groupIDToChangedMemberIDMap=%s" % (self, memberRows, groupIDToChangedMemberIDMap,))
- '''
- Started work here to get missing member names, but that is not needed right now, AFAI can tell
+ allowedObjectIDs = None
+ @inlineCallbacks
+ def allowedObjectIDs(acceptedGroupIDs):
+ if not hasattr(self, "__allowedObjectIDs"):
+ self.__allowedObjectIDs = yield self.expandGroupIDs(self._txn, acceptedGroupIDs)
+ returnValue(self.__allowedObjectIDs)
- # member names are not saved until resource is deleted, so get missing names from db
- idsForMissingNames = list(set([memberID for name, memberID, removed, revision in memberResults in memberResults if not name]))
+ @inlineCallbacks
+ def getMissingNames(ids, idToNameMap):
+ idsForMissingNames = list(set(ids) - set(idToNameMap.keys()))
+ if idsForMissingNames:
+ abo = schema.ADDRESSBOOK_OBJECT
+ memberIDNameRows = (
+ yield AddressBookObject._columnsWithResourceIDsQuery(
+ [abo.RESOURCE_ID, abo.RESOURCE_NAME],
+ idsForMissingNames
+ ).on(self._txn, resourceIDs=idsForMissingNames)
+ )
+ idToNameMap = dict(dict(idToNameMap), **dict(memberIDNameRows))
- abo = schema.ADDRESSBOOK_OBJECT
- memberIDNameRows = (
- yield self._columnsWithResourceIDsQuery(
- [abo.RESOURCE_ID, abo.RESOURCE_NAME],
- idsForMissingNames
- ).on(self._txn, resourceIDs=idsForMissingNames)
- ) if idsForMissingNames else []
- idToNameMap = dict(memberIDNameRows)
+ returnValue(idToNameMap)
- for i, (name, memberID, removed, revision) in enumerate(copy(memberResults)):
- memberResults[i] = (name if name else idToNameMap[memberID], memberID, removed, revision)
+ allIDs = set()
+ for groupID, memberID, removed in memberRows:
+ allIDs.add(groupID)
+ allIDs.add(memberID)
+
+ idToNameMap = yield getMissingNames(allIDs, {})
+ print("sharedChildResourceNamesSinceRevision:%s idToNameMap=%s" % (self, idToNameMap,))
+
+ path = self.name()
+ removedMemberIDs = set()
+ changedMemberIDs = set()
+
+ # TODO: use for query
+ allowedObjectIDs = yield self.expandGroupIDs(self._txn, acceptedGroupIDs)
+ print("sharedChildResourceNamesSinceRevision:%s acceptedGroupIDs:%s allowedObjectIDs=%s," % (self, acceptedGroupIDs, allowedObjectIDs,))
+
+ for groupID, memberID, removed in memberRows:
+
+ if memberID not in allowedObjectIDs or groupID not in allowedObjectIDs:
+ print("sharedChildResourceNamesSinceRevision:%s SKIP groupID:%s memberID=%s, wasdeleted=%s" % (self, groupID, memberID, wasdeleted,))
+ continue
+ print("sharedChildResourceNamesSinceRevision:%s groupID:%s memberID=%s, wasdeleted=%s" % (self, groupID, memberID, wasdeleted,))
+
+ if removed:
+ if sharerevision:
+ if depth == "1":
+ changed.add("%s/" % (path,))
+ else:
+ removedMemberIDs.add(memberID)
+
+ # Always report collection as changed
+ changed.add("%s/" % (path,))
+
+ # Resource changed - for depth "infinity" report resource as changed
+ if depth != "1":
+ changedMemberIDs.add(memberID)
+ changedMemberIDs.add(groupID)
+
+ print("sharedChildResourceNamesSinceRevision:%s changed:%s deleted=%s, removedMemberIDs=%s, changedMemberIDs=%s" % (self, changed, deleted, removedMemberIDs, changedMemberIDs))
+
'''
+ nameToIDMap = dict([(v, k) for k, v in idToNameMap.iteritems()])
- #TODO: Finish
+ for name, wasdeleted in results:
- path = self.name()
- for name, wasdeleted, revision in results:
+ id = nameToIDMap[name]
+ if id not in allowedObjectIDs:
+ print("sharedChildResourceNamesSinceRevision:%s SKIP name:%s id=%s, wasdeleted=%s" % (self, name, id, wasdeleted,))
+ continue
+
+ print("sharedChildResourceNamesSinceRevision:%s name:%s id=%s, wasdeleted=%s" % (self, name, id, wasdeleted,))
if wasdeleted:
if sharerevision:
if depth == "1":
@@ -532,14 +627,24 @@
else:
deleted.add("%s/%s" % (path, name,))
- for name, wasdeleted in results:
# Always report collection as changed
changed.add("%s/" % (path,))
- if name:
- # Resource changed - for depth "infinity" report resource as changed
- if depth != "1":
- changed.add("%s/%s" % (path, name,))
+ # Resource changed - for depth "infinity" report resource as changed
+ if depth != "1":
+ changed.add("%s/%s" % (path, name,))
+
+ print("sharedChildResourceNamesSinceRevision:%s changed:%s deleted=%s, removedMemberIDs=%s, changedMemberIDs=%s" % (self, changed, deleted, removedMemberIDs, changedMemberIDs))
+ '''
+
+ # for changes, get object names all at once here
+ idToNameMap = yield getMissingNames(removedMemberIDs | changedMemberIDs, idToNameMap)
+ for removedMemberID in removedMemberIDs:
+ deleted.add("%s/%s" % (path, idToNameMap[removedMemberID],))
+
+ for changedMemberID in changedMemberIDs:
+ changed.add("%s/%s" % (path, idToNameMap[changedMemberID],))
+
returnValue((changed, deleted))
@@ -798,9 +903,7 @@
ownerHome = yield home.ownerHomeWithChildID(ownerAddressBookID)
if ownerHome not in ownerHomeToDataRowMap:
groupBindRow[0] = _BIND_MODE_WRITE
- groupBindRow[3] = None # bindName
- groupBindRow[4] = None # bindStatus
- groupBindRow[6] = None # bindMessage
+ groupBindRow[3:7] = 4 * [None] # bindName, bindStatus, bindRevision, bindMessage
ownerHomeToDataRowMap[ownerHome] = groupBindRow
if ownerHomeToDataRowMap:
@@ -892,16 +995,18 @@
groupBindRows = yield AddressBookObject._bindForHomeIDAndAddressBookID.on(
home._txn, homeID=home._resourceID, addressbookID=ownerAddressBook._resourceID
)
+ # prefer a bindStatus match, otherwise get row for cache
+ matchingGroupBindRows = [groupBindRow for groupBindRow in groupBindRows if (groupBindRow[4] == _BIND_STATUS_ACCEPTED) == bool(accepted)]
+ if matchingGroupBindRows:
+ groupBindRows = matchingGroupBindRows
+
for groupBindRow in groupBindRows:
- if (groupBindRow[4] == _BIND_STATUS_ACCEPTED) == bool(accepted):
- groupBindRow.insert(AddressBookObject.bindColumnCount, ownerAddressBook._resourceID)
- groupBindRow.insert(AddressBookObject.bindColumnCount + 1, groupBindRow[4])
- groupBindRow[0] = _BIND_MODE_WRITE
- groupBindRow[3] = None # bindName
- groupBindRow[4] = None # bindStatus
- groupBindRow[6] = None # bindMessage
- rows = [groupBindRow]
- break
+ groupBindRow.insert(AddressBookObject.bindColumnCount, ownerAddressBook._resourceID)
+ groupBindRow.insert(AddressBookObject.bindColumnCount + 1, groupBindRow[4])
+ groupBindRow[0] = _BIND_MODE_WRITE
+ groupBindRow[3:7] = 4 * [None] # bindName, bindStatus, bindRevision, bindMessage
+ rows = [groupBindRow]
+ break
if rows and queryCacher:
# Cache the result
@@ -1258,7 +1363,8 @@
bindNameRows = yield self._updateBindColumnsQuery(columnMap).on(
self._txn,
- resourceID=self._resourceID, homeID=shareeView.viewerHome()._resourceID
+ resourceID=self._resourceID,
+ homeID=shareeView.viewerHome()._resourceID
)
# update affected attributes
@@ -1270,9 +1376,9 @@
if shareeView._bindStatus == _BIND_STATUS_ACCEPTED:
if 0 == previouslyAcceptedBindCount:
yield shareeView._initSyncToken()
- yield shareeView._initBindRevision()
shareeView.viewerHome()._children[self.shareeName()] = shareeView
shareeView.viewerHome()._children[shareeView._resourceID] = shareeView
+ yield shareeView._initBindRevision()
elif shareeView._bindStatus == _BIND_STATUS_DECLINED:
if 1 == previouslyAcceptedBindCount:
yield shareeView._deletedSyncToken(sharedRemoval=True)
@@ -1342,7 +1448,7 @@
# Must send notification to ensure cache invalidation occurs
yield self.notifyPropertyChanged()
- # delete binds including invites
+ # delete bind table rows for this share
deletedBindNameRows = yield self._deleteBindForResourceIDAndHomeID.on(self._txn, resourceID=self._resourceID,
homeID=shareeHome._resourceID
)
@@ -1385,6 +1491,7 @@
self._bindStatus = None
self._bindMessage = None
self._bindName = None
+ self._bindRevision = None
super(AddressBookObject, self).__init__(addressbook, name, uid, resourceID, options)
self._options = {} if options is None else options
@@ -1421,15 +1528,16 @@
raise HTTPError(FORBIDDEN)
if not self.owned() and not self.addressbook().fullyShared():
- readWriteObjectIDs = []
readWriteGroupIDs = yield self.addressbook().readWriteGroupIDs()
- if readWriteGroupIDs:
- readWriteObjectIDs = yield self.addressbook().expandGroupIDs(self._txn, readWriteGroupIDs)
+ readWriteObjectIDs = (
+ yield self.addressbook().expandGroupIDs(self._txn, readWriteGroupIDs)
+ ) if readWriteGroupIDs else []
# can't delete item in read-only shared group, even if user has addressbook unbind
if self._resourceID not in readWriteObjectIDs:
raise HTTPError(FORBIDDEN)
+ '''
# get sync token for delete now
yield self.addressbook()._deleteRevision(self.name())
@@ -1444,43 +1552,58 @@
)
groupIDs = [groupIDRow[0] for groupIDRow in groupIDRows]
if groupIDs:
+ print("remove:%s _removeMemberIDFromGroupIDsQuery:groupIDs=%s memberID=%s" % (self, groupIDs, self._resourceID,))
yield self._removeMemberIDFromGroupIDsQuery(groupIDs).on(self._txn,
groupIDs=groupIDs,
addressbookID=self._ownerAddressBookResourceID,
memberID=self._resourceID,
- revision=self.addressbook()._syncTokenRevision,
+ revision=self._syncTokenRevision,
)
+
else:
# get sync token for delete now
yield self.addressbook()._deleteRevision(self.name())
+ '''
+ # get sync token for delete now
+ yield self.addressbook()._deleteRevision(self.name())
+
aboMembers = schema.ABO_MEMBERS
- groupIDRows = yield Select(
- [aboMembers.GROUP_ID],
+ groupIDRevisions = yield Select(
+ [aboMembers.GROUP_ID, aboMembers.REVISION],
From=aboMembers,
Where=(aboMembers.MEMBER_ID == self._resourceID)
.And(aboMembers.REMOVED == False),
).on(self._txn)
- groupIDs = [groupIDRow[0] for groupIDRow in groupIDRows]
- if self.owned() or self.addressbook().fullyShared():
+ groupIDsToRemoveFrom = (
+ [groupIDRow[0] for groupIDRow in groupIDRevisions]
+ if self.owned() or self.addressbook().fullyShared()
+ else readWriteObjectIDs
+ )
+
+ if groupIDsToRemoveFrom:
# remove memberships
- if groupIDs:
- yield self._removeMemberIDFromGroupIDsQuery(groupIDs).on(self._txn,
- groupIDs=groupIDs,
- addressbookID=self._ownerAddressBookResourceID,
- memberID=self._resourceID,
- revision=self.addressbook()._syncTokenRevision,
- )
+ print("remove:%s _removeMemberIDFromGroupIDsQuery:revision=%s groupIDs=%s memberID=%s" % (self, self._ownerAddressBookResourceID, groupIDsToRemoveFrom, self._resourceID,))
+ yield self._removeMemberIDFromGroupIDsQuery(groupIDsToRemoveFrom).on(self._txn,
+ groupIDs=groupIDsToRemoveFrom,
+ addressbookID=self._ownerAddressBookResourceID,
+ memberID=self._resourceID,
+ revision=self._syncTokenRevision,
+ )
# add to foreign member table row by UID (aboForeignMembers on address books)
memberAddress = "urn:uuid:" + self._uid
aboForeignMembers = schema.ABO_FOREIGN_MEMBERS
- for groupID in set(groupIDs) - set([self._ownerAddressBookResourceID]):
+ if groupIDRevisions:
+ print("updateDatabase:%s _insertForeignMemberAddrQuery:revision=%s foreignMemberAddrToAdd=%s" % (self, self._syncTokenRevision, groupIDRevisions,))
+
+ for groupID, revision in groupIDRevisions:#set(groupIDs) - set([self._ownerAddressBookResourceID]):
yield Insert(
{aboForeignMembers.GROUP_ID: groupID,
aboForeignMembers.ADDRESSBOOK_ID: self._ownerAddressBookResourceID,
- aboForeignMembers.MEMBER_ADDRESS: memberAddress, }
+ aboForeignMembers.MEMBER_ADDRESS: memberAddress,
+ aboForeignMembers.REVISION: revision, }
).on(self._txn)
if self.kind() == _ABO_KIND_GROUP:
@@ -1490,16 +1613,19 @@
[aboMembers.MEMBER_ID],
From=aboMembers,
Where=(aboMembers.GROUP_ID == self._resourceID)
+ .And(aboMembers.REMOVED == False),
).on(self._txn)
memberIDsToRemove = [memberIDRow[0] for memberIDRow in memberIDRows]
- yield self._removeMemberIDsFromGroupIDQuery(memberIDsToRemove).on(
- self._txn,
- groupID=self._resourceID,
- addressbookID=self._ownerAddressBookResourceID,
- memberIDs=memberIDsToRemove,
- revision=self.addressbook()._syncTokenRevision,
- )
+ if memberIDsToRemove:
+ print("remove:%s _removeMemberIDsFromGroupIDQuery:revision=%s groupID=%s memberIDsToRemove=%s" % (self, self._ownerAddressBookResourceID, self._resourceID, memberIDsToRemove,))
+ yield self._removeMemberIDsFromGroupIDQuery(memberIDsToRemove).on(
+ self._txn,
+ groupID=self._resourceID,
+ addressbookID=self._ownerAddressBookResourceID,
+ memberIDs=memberIDsToRemove,
+ revision=self._syncTokenRevision,
+ )
yield super(AddressBookObject, self).remove()
self._kind = None
@@ -1634,6 +1760,7 @@
self._bindStatus = bindStatus
self._bindMessage = bindMessage
self._bindName = bindName
+ self._bindRevision = bindRevision
yield self._initIsShared()
@@ -1896,7 +2023,6 @@
{aboMembers.GROUP_ID: Parameter("groupID"),
aboMembers.ADDRESSBOOK_ID: Parameter("addressbookID"),
aboMembers.MEMBER_ID: Parameter("memberID"),
- #aboMembers.RESOURCE_NAME: Parameter("resourceName"),
aboMembers.REVISION: Parameter("revision"),
#aboMembers.REMOVED: False,
}
@@ -2049,27 +2175,30 @@
)
)[0]
- # delete foreign members table row for this object
+ # delete foreign members table rows for this object, keeping revision
groupIDRows = yield Delete(
aboForeignMembers,
Where=aboForeignMembers.MEMBER_ADDRESS == "urn:uuid:" + self._uid,
- Return=aboForeignMembers.GROUP_ID
+ Return=[aboForeignMembers.GROUP_ID, aboForeignMembers.REVISION]
).on(self._txn)
- groupIDs = set([groupIDRow[0] for groupIDRow in groupIDRows])
+ groupIDToRevisionMap = dict(groupIDRows)
# add vCard to writable groups
if not self.owned() and not self.addressbook().fullyShared():
readWriteGroupIDs = yield self.addressbook().readWriteGroupIDs()
assert readWriteGroupIDs, "no access"
- groupIDs |= set(readWriteGroupIDs)
+ for id in readWriteGroupIDs:
+ groupIDToRevisionMap[id] = self._syncTokenRevision
# add to member table rows
- for groupID in groupIDs:
+ if groupIDToRevisionMap:
+ print("updateDatabase:%s _insertMemberIDQuery:revision=%s groupIDToRevisionMap=%s memberIDToAdd=%s" % (self, self._syncTokenRevision, groupIDToRevisionMap, self._resourceID,))
+ for groupID, revision in groupIDToRevisionMap.iteritems():
yield self._insertMemberIDQuery.on(self._txn,
groupID=groupID,
addressbookID=self._ownerAddressBookResourceID,
memberID=self._resourceID,
- revision=self.addressbook()._syncTokenRevision,
+ revision=revision,
)
else:
@@ -2097,31 +2226,53 @@
memberIDsToAdd = set(memberIDs) - set(currentMemberIDs) - set(removedMemberIDs)
memberIDsToReadd = set(memberIDs) & set(removedMemberIDs)
+ if memberIDsToAdd:
+ print("updateDatabase:%s _insertMemberIDQuery:revision=%s groupID=%s memberIDsToAdd=%s" % (self, self._syncTokenRevision, self._resourceID, memberIDsToAdd,))
for memberIDToAdd in memberIDsToAdd:
yield self._insertMemberIDQuery.on(self._txn,
groupID=self._resourceID,
addressbookID=self._ownerAddressBookResourceID,
memberID=memberIDToAdd,
- revision=self.addressbook()._syncTokenRevision,
+ revision=self._syncTokenRevision,
)
if memberIDsToReadd:
+ print("updateDatabase:%s _addRemovedMemberIDsToGroupIDQuery:revision=%s groupID=%s memberIDsToRemove=%s" % (self, self._syncTokenRevision, self._resourceID, memberIDsToReadd,))
yield self._addRemovedMemberIDsToGroupIDQuery(memberIDsToReadd).on(self._txn,
groupID=self._resourceID,
addressbookID=self._ownerAddressBookResourceID,
memberIDs=memberIDsToReadd,
- revision=self.addressbook()._syncTokenRevision,
+ revision=self._syncTokenRevision,
)
if memberIDsToRemove:
+ print("updateDatabase:%s _removeMemberIDsFromGroupIDQuery:revision=%s groupID=%s memberIDsToRemove=%s" % (self, self._syncTokenRevision, self._resourceID, memberIDsToRemove,))
yield self._removeMemberIDsFromGroupIDQuery(memberIDsToRemove).on(
self._txn,
groupID=self._resourceID,
addressbookID=self._ownerAddressBookResourceID,
memberIDs=memberIDsToRemove,
- revision=self.addressbook()._syncTokenRevision,
+ revision=self._syncTokenRevision,
)
+ if memberIDsToAdd or memberIDsToRemove:
+ # get expanded remove
+ memberIDsToAddRemoved = yield AddressBook.expandGroupIDs(self.txn, memberIDsToAdd | memberIDsToRemove, includeGroupIDs=False)
+ if memberIDsToAddRemoved:
+ print("updateDatabase:%s _insertMemberIDQuery:revision=%s groupID=%s memberIDsToAddRemoved=%s" % (self, self._syncTokenRevision, self._resourceID, memberIDsToAddRemoved,))
+ for memberIDToAddRemoved in memberIDsToAddRemoved:
+ aboMembers = schema.ABO_MEMBERS
+ return Insert(
+ {aboMembers.GROUP_ID: self._resourceID,
+ aboMembers.ADDRESSBOOK_ID: self._ownerAddressBookResourceID,
+ aboMembers.MEMBER_ID: memberIDToAddRemoved,
+ aboMembers.REVISION: self._syncTokenRevision,
+ aboMembers.REMOVED: True,
+ }
+ )
+
+
+
# don't bother with aboForeignMembers on address books
if self._resourceID != self._ownerAddressBookResourceID:
@@ -2140,11 +2291,14 @@
self._txn, memberAddrs=foreignMemberAddrsToDelete
)
+ if foreignMemberAddrsToAdd:
+ print("updateDatabase:%s _insertForeignMemberAddrQuery:revision=%s foreignMemberAddrToAdd=%s" % (self, self._syncTokenRevision, foreignMemberAddrsToAdd,))
for foreignMemberAddrToAdd in foreignMemberAddrsToAdd:
yield Insert(
{aboForeignMembers.GROUP_ID: self._resourceID,
aboForeignMembers.ADDRESSBOOK_ID: self._ownerAddressBookResourceID,
- aboForeignMembers.MEMBER_ADDRESS: foreignMemberAddrToAdd, }
+ aboForeignMembers.MEMBER_ADDRESS: foreignMemberAddrToAdd,
+ aboForeignMembers.REVISION: self._syncTokenRevision, }
).on(self._txn)
@@ -2490,21 +2644,11 @@
returnValue(bindName)
- @inlineCallbacks
- def _initBindRevision(self):
- yield self.addressbook()._initBindRevision()
+ @property
+ def _syncTokenRevision(self):
+ return self.addressbook()._syncTokenRevision
- bind = self._bindSchema
- yield self._updateBindColumnsQuery(
- {bind.BIND_REVISION : Parameter("revision"), }).on(
- self._txn,
- revision=self.addressbook()._bindRevision,
- resourceID=self._resourceID,
- homeID=self.viewerHome()._resourceID,
- )
- yield self.invalidateQueryCache()
-
@inlineCallbacks
def updateShare(self, shareeView, mode=None, status=None, message=None):
"""
@@ -2553,7 +2697,8 @@
bindNameRows = yield self._updateBindColumnsQuery(columnMap).on(
self._txn,
- resourceID=self._resourceID, homeID=shareeView.viewerHome()._resourceID
+ resourceID=self._resourceID,
+ homeID=shareeView.viewerHome()._resourceID
)
# update affected attributes
@@ -2565,9 +2710,9 @@
if shareeView._bindStatus == _BIND_STATUS_ACCEPTED:
if 0 == previouslyAcceptedBindCount:
yield shareeView.addressbook()._initSyncToken()
- yield shareeView._initBindRevision()
shareeView.viewerHome()._children[self.addressbook().shareeName()] = shareeView.addressbook()
shareeView.viewerHome()._children[shareeView._resourceID] = shareeView.addressbook()
+ yield shareeView._initBindRevision()
elif shareeView._bindStatus != _BIND_STATUS_INVITED:
if 1 == previouslyAcceptedBindCount:
yield shareeView.addressbook()._deletedSyncToken(sharedRemoval=True)
Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/test/test_sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/test/test_sql.py 2013-09-07 03:09:24 UTC (rev 11660)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/carddav/datastore/test/test_sql.py 2013-09-09 22:41:27 UTC (rev 11661)
@@ -901,8 +901,9 @@
self.assertEqual(normalAB._bindRevision, 0)
otherHome = yield self.homeUnderTest(name="home2")
otherGroup = yield otherHome.objectWithShareUID(newGroupShareUID)
+ self.assertNotEqual(otherGroup._bindRevision, 0)
otherAB = otherGroup.addressbook()
- self.assertNotEqual(otherAB._bindRevision, 0)
+ self.assertEqual(otherAB._bindRevision, None)
@inlineCallbacks
@@ -952,8 +953,9 @@
self.assertEqual(normalAB._bindRevision, 0)
otherHome = yield self.homeUnderTest(name="home2")
otherGroup = yield otherHome.invitedObjectWithShareUID(newGroupShareUID)
+ self.assertEqual(otherGroup._bindRevision, 0)
otherAB = otherGroup.addressbook()
- self.assertEqual(otherAB._bindRevision, 0)
+ self.assertEqual(otherAB._bindRevision, None)
yield self.commit()
normalAB = yield self.addressbookUnderTest(home="home3")
@@ -967,8 +969,9 @@
self.assertEqual(normalAB._bindRevision, 0)
otherHome = yield self.homeUnderTest(name="home2")
otherGroup = yield otherHome.objectWithShareUID(newGroupShareUID)
+ self.assertNotEqual(otherGroup._bindRevision, 0)
otherAB = otherGroup.addressbook()
- self.assertNotEqual(otherAB._bindRevision, 0)
+ self.assertEqual(otherAB._bindRevision, None)
@inlineCallbacks
@@ -1022,23 +1025,28 @@
self.assertEqual(normalAB._bindRevision, 0)
otherHome = yield self.homeUnderTest(name="home2")
otherGroup = yield otherHome.objectWithShareUID(newGroupShareUID)
+ self.assertNotEqual(otherGroup._bindRevision, 0)
otherAB = otherGroup.addressbook()
- self.assertNotEqual(otherAB._bindRevision, 0)
+ self.assertEqual(otherAB._bindRevision, None)
- changed, deleted = yield otherAB.resourceNamesSinceRevision(otherAB._bindRevision - 1)
- self.assertNotEqual(len(changed), 0)
+ changed, deleted = yield otherAB.resourceNamesSinceRevision(otherGroup._bindRevision - 1)
+ print("revision=%s, changed=%s, deleted=%s" % (otherGroup._bindRevision - 1, changed, deleted,))
+ self.assertEqual(set(changed), set(['1.vcf', '4.vcf', '2.vcf', ]))
self.assertEqual(len(deleted), 0)
- changed, deleted = yield otherAB.resourceNamesSinceRevision(otherAB._bindRevision)
+ changed, deleted = yield otherAB.resourceNamesSinceRevision(otherGroup._bindRevision)
+ print("revision=%s, changed=%s, deleted=%s" % (otherGroup._bindRevision, changed, deleted,))
self.assertEqual(len(changed), 0)
self.assertEqual(len(deleted), 0)
- for depth in ("1", "infinity",):
- changed, deleted = yield otherHome.resourceNamesSinceRevision(otherAB._bindRevision - 1, depth)
- self.assertNotEqual(len(changed), 0)
+ for depth, result in (("1", ['home3/']), ("infinity", ['home3/1.vcf', 'home3/4.vcf', 'home3/2.vcf', 'home3/'])):
+ changed, deleted = yield otherHome.resourceNamesSinceRevision(otherGroup._bindRevision - 1, depth)
+ print("revision=%s, depth=%s, changed=%s, deleted=%s" % (otherGroup._bindRevision - 1, depth, changed, deleted,))
+ self.assertEqual(set(changed), set(result))
self.assertEqual(len(deleted), 0)
- changed, deleted = yield otherHome.resourceNamesSinceRevision(otherAB._bindRevision, depth)
+ changed, deleted = yield otherHome.resourceNamesSinceRevision(otherGroup._bindRevision, depth)
+ print("revision=%s, depth=%s, changed=%s, deleted=%s" % (otherGroup._bindRevision, depth, changed, deleted,))
self.assertEqual(len(changed), 0)
self.assertEqual(len(deleted), 0)
Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql.py 2013-09-07 03:09:24 UTC (rev 11660)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql.py 2013-09-09 22:41:27 UTC (rev 11661)
@@ -1905,6 +1905,7 @@
@type depth: C{str}
"""
+ print("CommonHome: resourceNamesSinceRevision:%s revision:%s, depth:%s" % (self, revision, depth))
results = [
(
path if path else (collection if collection else ""),
@@ -1933,7 +1934,6 @@
deleted.add("%s/" % (path,))
deleted_collections.add(path)
- for path, name, wasdeleted in results:
if path not in deleted_collections:
# Always report collection as changed
changed.add("%s/" % (path,))
@@ -2321,6 +2321,7 @@
@type revision: C{int}
"""
+ print("_SharedSyncLogic: resourceNamesSinceRevision:%s revision:%s" % (self, revision,))
results = [
(name if name else "", deleted)
for name, deleted in
@@ -4108,6 +4109,7 @@
@type revision: C{int}
"""
+ print("CommonHomeChild: resourceNamesSinceRevision:%s revision:%s" % (self, revision,))
if revision < self._bindRevision:
revision = 0
return super(CommonHomeChild, self).resourceNamesSinceRevision(revision)
@@ -4162,14 +4164,13 @@
else:
deleted.add("%s/%s" % (path, name,))
- for path, name, wasdeleted in results:
# Always report collection as changed
changed.add("%s/" % (path,))
- if name:
- # Resource changed - for depth "infinity" report resource as changed
- if depth != "1":
- changed.add("%s/%s" % (path, name,))
+ # Resource changed - for depth "infinity" report resource as changed
+ if depth != "1":
+ changed.add("%s/%s" % (path, name,))
+
returnValue((changed, deleted))
Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql_schema/current-oracle-dialect.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql_schema/current-oracle-dialect.sql 2013-09-07 03:09:24 UTC (rev 11660)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql_schema/current-oracle-dialect.sql 2013-09-09 22:41:27 UTC (rev 11661)
@@ -255,7 +255,6 @@
"GROUP_ID" integer not null,
"ADDRESSBOOK_ID" integer not null references ADDRESSBOOK_HOME on delete cascade,
"MEMBER_ID" integer not null,
- "RESOURCE_NAME" nvarchar2(255),
"REVISION" integer not null,
"REMOVED" integer default 0 not null,
primary key("GROUP_ID", "MEMBER_ID")
Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql_schema/current.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql_schema/current.sql 2013-09-07 03:09:24 UTC (rev 11660)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql_schema/current.sql 2013-09-09 22:41:27 UTC (rev 11661)
@@ -462,7 +462,6 @@
GROUP_ID integer not null, -- references ADDRESSBOOK_OBJECT on delete cascade, -- AddressBook Object's (kind=='group') RESOURCE_ID
ADDRESSBOOK_ID integer not null references ADDRESSBOOK_HOME on delete cascade,
MEMBER_ID integer not null, -- references ADDRESSBOOK_OBJECT, -- member AddressBook Object's RESOURCE_ID
- RESOURCE_NAME varchar(255),
REVISION integer default nextval('REVISION_SEQ') not null,
REMOVED boolean default false not null,
@@ -482,6 +481,7 @@
GROUP_ID integer not null references ADDRESSBOOK_OBJECT on delete cascade, -- AddressBook Object's (kind=='group') RESOURCE_ID
ADDRESSBOOK_ID integer not null references ADDRESSBOOK_HOME on delete cascade,
MEMBER_ADDRESS varchar(255) not null, -- member AddressBook Object's 'calendar' address
+ REVISION integer default nextval('REVISION_SEQ') not null,
primary key (GROUP_ID, MEMBER_ADDRESS) -- implicit index
);
Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql 2013-09-07 03:09:24 UTC (rev 11660)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_24_to_25.sql 2013-09-09 22:41:27 UTC (rev 11661)
@@ -27,8 +27,6 @@
alter table ABO_MEMBERS
drop ("abo_members_group_id_fkey");
alter table ABO_MEMBERS
- add ("RESOURCE_NAME" varchar(255));
-alter table ABO_MEMBERS
add ("REVISION" integer default nextval('REVISION_SEQ') not null);
alter table ABO_MEMBERS
add ("REMOVED" boolean default false not null);
Modified: CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql 2013-09-07 03:09:24 UTC (rev 11660)
+++ CalendarServer/branches/users/gaya/sharedgroupfixes/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_24_to_25.sql 2013-09-09 22:41:27 UTC (rev 11661)
@@ -25,7 +25,6 @@
alter table ABO_MEMBERS
drop constraint abo_members_member_id_fkey,
drop constraint abo_members_group_id_fkey,
- add column RESOURCE_NAME varchar(255),
add column REVISION integer default nextval('REVISION_SEQ') not null,
add column REMOVED boolean default false not null;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130909/3099b1fc/attachment-0001.html>
More information about the calendarserver-changes
mailing list