[CalendarServer-changes] [10307] CalendarServer/branches/users/gaya/sharedgroups/txdav
source_changes at macosforge.org
source_changes at macosforge.org
Tue Jan 15 16:03:16 PST 2013
Revision: 10307
http://trac.calendarserver.org//changeset/10307
Author: gaya at apple.com
Date: 2013-01-15 16:03:16 -0800 (Tue, 15 Jan 2013)
Log Message:
-----------
Checkpoint changes --- on the way to making shared groups work with the current, non-final schema
Modified Paths:
--------------
CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py
CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py
CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql
Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py 2013-01-15 21:15:06 UTC (rev 10306)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py 2013-01-16 00:03:16 UTC (rev 10307)
@@ -27,7 +27,7 @@
]
from twext.enterprise.dal.syntax import Delete, Insert, Len, Parameter, \
- Update, Select, utcNowSQL
+ Update, Union, Select, utcNowSQL
from twext.python.clsprop import classproperty
from twext.web2.http_headers import MimeType
@@ -54,7 +54,9 @@
ADDRESSBOOK_OBJECT_AND_BIND_TABLE, \
ADDRESSBOOK_OBJECT_REVISIONS_AND_BIND_TABLE, \
_ABO_KIND_PERSON, _ABO_KIND_GROUP, _ABO_KIND_RESOURCE, \
- _ABO_KIND_LOCATION, schema
+ _ABO_KIND_LOCATION, schema, \
+ _BIND_MODE_OWN, _BIND_STATUS_ACCEPTED
+
from txdav.xml.rfc2518 import ResourceType
from zope.interface.declarations import implements
@@ -280,12 +282,37 @@
@inlineCallbacks
+ def _ownerGroupAndAddressBook(self):
+ """
+ Find the owner shared group and owner address book. owner shared group may be None
+ """
+ ownerGroup = None
+ if self.owned():
+ yield None
+ ownerAddressBook = self
+ else:
+ ownerAddressBook = yield self.ownerAddressBookHome().childWithID(self._resourceID)
+ if not ownerAddressBook:
+ for addressbook in (yield self.ownerAddressBookHome().addressbooks()):
+ ownerGroup = yield addressbook.objectResourceWithID(self._resourceID)
+ if ownerGroup:
+ ownerAddressBook = addressbook
+ break
+
+ returnValue((ownerGroup, ownerAddressBook))
+
+
+ @inlineCallbacks
+ def ownerGroup(self):
+ if not hasattr(self, "_ownerGroup"):
+ self._ownerGroup, self._ownerAddressBook = yield self._ownerGroupAndAddressBook()
+ returnValue(self._ownerGroup)
+
+
+ @inlineCallbacks
def ownerAddressBook(self):
if not hasattr(self, "_ownerAddressBook"):
- if self.owned():
- self._ownerAddressBook = self
- else:
- self._ownerAddressBook = yield self.ownerAddressBookHome().childWithID(self._resourceID)
+ self._ownerGroup, self._ownerAddressBook = yield self._ownerGroupAndAddressBook()
returnValue(self._ownerAddressBook)
@@ -315,7 +342,125 @@
yield None
returnValue(self.name())
+ @classmethod
+ def _bindsFor(cls, where): #@NoSelf
+ def columns(bind): #@NoSelf
+ return [bind.BIND_MODE,
+ bind.HOME_RESOURCE_ID,
+ bind.RESOURCE_ID,
+ bind.RESOURCE_NAME,
+ bind.BIND_STATUS,
+ bind.MESSAGE]
+
+ addressbookBind = cls._bindSchema
+ groupBind = AddressBookObject._bindSchema
+ return Select(
+ columns(addressbookBind),
+ From=addressbookBind,
+ Where=where(addressbookBind),
+ SetExpression=Union(
+ Select(
+ columns(groupBind),
+ From=groupBind,
+ Where=where(groupBind),
+ ),
+ optype=Union.OPTYPE_ALL,
+ )
+ )
+
+
+ @classproperty
+ def _invitedBindForResourceID(cls): #@NoSelf
+ return cls._bindsFor(lambda bind: ((bind.RESOURCE_ID == Parameter("resourceID"))
+ .And(bind.BIND_STATUS != _BIND_STATUS_ACCEPTED)
+ ))
+
+
+ @classproperty
+ def _sharedBindForResourceID(cls): #@NoSelf
+ return cls._bindsFor(lambda bind: ((bind.RESOURCE_ID == Parameter("resourceID"))
+ .And(bind.BIND_STATUS == _BIND_STATUS_ACCEPTED)
+ .And(bind.BIND_MODE != _BIND_MODE_OWN)
+ ))
+
+
+ @classproperty
+ def _invitedBindForHomeID(cls): #@NoSelf
+ return cls._bindsFor(lambda bind: ((bind.HOME_RESOURCE_ID == Parameter("homeID"))
+ .And(bind.BIND_STATUS != _BIND_STATUS_ACCEPTED)
+ ))
+
+
+ @classproperty
+ def _invitedBindForNameAndHomeID(cls): #@NoSelf
+ return cls._bindsFor(lambda bind: ((bind.RESOURCE_NAME == Parameter("name"))
+ .And(bind.HOME_RESOURCE_ID == Parameter("homeID"))
+ .And(bind.BIND_STATUS != _BIND_STATUS_ACCEPTED)
+ ))
+
+
+ @classproperty
+ def _childForNameAndHomeID(cls): #@NoSelf
+ return cls._bindsFor(lambda bind: ((bind.RESOURCE_NAME == Parameter("name"))
+ .And(bind.HOME_RESOURCE_ID == Parameter("homeID"))
+ .And(bind.BIND_STATUS == _BIND_STATUS_ACCEPTED)
+ ))
+
+
+ @classproperty
+ def _bindForResourceIDAndHomeID(cls): #@NoSelf
+ return cls._bindsFor(lambda bind: ((bind.RESOURCE_ID == Parameter("resourceID"))
+ .And(bind.HOME_RESOURCE_ID == Parameter("homeID"))
+ ))
+
+
+ @classproperty
+ def _metadataByIDQuery(cls): #@NoSelf
+ """
+ DAL query to retrieve created/modified dates based on a resource ID.
+ """
+ child = cls._homeChildMetaDataSchema
+ abo = schema.ADDRESSBOOK_OBJECT
+ return Select(
+ cls.metadataColumns(),
+ From=child,
+ Where=child.RESOURCE_ID == Parameter("resourceID"),
+ SetExpression=Union(
+ Select(
+ [abo.CREATED, abo.MODIFIED],
+ From=abo,
+ Where=abo.RESOURCE_ID == Parameter("resourceID"),
+ ),
+ optype=Union.OPTYPE_ALL,
+ )
+ )
+
+
+ @classproperty
+ def _changeABForSharedGroupLastModifiedQuery(cls): #@NoSelf
+ schema = AddressBook._objectSchema
+ return Update({schema.MODIFIED: utcNowSQL},
+ Where=schema.RESOURCE_ID == Parameter("resourceID"),
+ Return=schema.MODIFIED)
+
+
+ @inlineCallbacks
+ def _bumpModified(self, subtxn):
+ print ("_bumpModified:self = %s" % (self,))
+
+ yield self._lockLastModifiedQuery.on(subtxn, resourceID=self._resourceID)
+
+ # can't call self.ownerGroup() on a subtranaction,
+ # So just try AB schema first, then ABOBject schema
+ result = yield self._changeLastModifiedQuery.on(subtxn, resourceID=self._resourceID)
+
+ if not result:
+ result = yield self._changeABForSharedGroupLastModifiedQuery.on(subtxn, resourceID=self._resourceID)
+
+ returnValue(result)
+
+
class AddressBookObject(CommonObjectResource, AddressBookSharingMixIn):
implements(IAddressBookObject)
@@ -377,7 +522,7 @@
aboMembers = schema.ABO_MEMBERS
aboForeignMembers = schema.ABO_FOREIGN_MEMBERS
- ownerGroup = yield self.ownerGroup()
+ ownerGroup = yield self._addressbook.ownerGroup()
if ownerGroup:
# convert delete in sharee shared group address book to remove of memberships
# that make this object visible to the sharee
@@ -389,7 +534,7 @@
yield self._deleteMembersWithMemberIDAndGroupIDsQuery(self._resourceID, objectIDs).on(
self._txn, groupIDs=objectIDs)
- ownerAddressBook = yield self.ownerAddressBook()
+ ownerAddressBook = yield self._addressbook.ownerAddressBook()
yield self._changeAddressBookRevision(ownerAddressBook)
else:
@@ -551,7 +696,7 @@
obj.MD5,
Len(obj.TEXT),
obj.CREATED,
- obj.MODIFIED
+ obj.MODIFIED,
]
@@ -645,43 +790,12 @@
else:
if self._addressbook._resourceID != self._ownerAddressBookResourceID:
# update revisions table of shared group's containing address book
- ownerAddressBook = yield self.ownerAddressBook()
+ ownerAddressBook = yield self._addressbook.ownerAddressBook()
yield self._changeAddressBookRevision(ownerAddressBook, inserting)
self._component = component
- @inlineCallbacks
- def _ownerGroupAndAddressBook(self):
- """
- Find the owner shared group and owner address book. owner shared group may be None
- """
- ownerGroup = None
- ownerAddressBook = yield self._addressbook.ownerAddressBook()
- if not ownerAddressBook:
- for addressbook in (yield self._addressbook.ownerAddressBookHome().addressbooks()):
- ownerGroup = yield addressbook.objectResourceWithID(self._addressbook._resourceID)
- if ownerGroup:
- ownerAddressBook = addressbook
- break
-
- returnValue((ownerGroup, ownerAddressBook))
-
-
- @inlineCallbacks
- def ownerGroup(self):
- if not hasattr(self, "_ownerGroup"):
- self._ownerGroup, self._ownerAddressBook = yield self._ownerGroupAndAddressBook()
- returnValue(self._ownerGroup)
-
-
- @inlineCallbacks
- def ownerAddressBook(self):
- if not hasattr(self, "_ownerAddressBook"):
- self._ownerGroup, self._ownerAddressBook = yield self._ownerGroupAndAddressBook()
- returnValue(self._ownerAddressBook)
-
-
@classmethod
def _resourceIDAndUIDForUIDsAndAddressBookResourceIDQuery(cls, uids): #@NoSelf
abo = schema.ADDRESSBOOK_OBJECT
@@ -735,7 +849,7 @@
# For shared groups: Non owner may NOT add group members not currently in group!
# (Or it would be possible to troll for unshared vCard UIDs and make them shared.)
if not self._ownerAddressBookResourceID:
- ownerAddressBook = yield self.ownerAddressBook()
+ ownerAddressBook = yield self._addressbook.ownerAddressBook()
self._ownerAddressBookResourceID = ownerAddressBook._resourceID
if self._kind == _ABO_KIND_GROUP:
@@ -756,7 +870,7 @@
foreignMemberAddrs.extend(["urn:uuid:" + missingUID for missingUID in set(memberUIDs) - set(foundUIDs)])
#in shared group, all members must be inside the shared group
- ownerGroup = yield self.ownerGroup()
+ ownerGroup = yield self._addressbook.ownerGroup()
if ownerGroup:
if foreignMemberAddrs or \
set(memberIDs) - set((yield ownerGroup._allGroupObjectIDs())):
@@ -824,9 +938,9 @@
# groupIDs.append(self._ownerAddressBookResourceID)
# add owner group if there is one
- ownerGroup = yield self.ownerGroup()
+ ownerGroup = yield self._addressbook.ownerGroup()
if ownerGroup:
- groupIDs.append(self._ownerGroup._resourceID)
+ groupIDs.append(ownerGroup._resourceID)
# add to member table rows
for groupID in groupIDs:
Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py 2013-01-15 21:15:06 UTC (rev 10306)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py 2013-01-16 00:03:16 UTC (rev 10307)
@@ -2169,7 +2169,7 @@
L{_BIND_MODE_WRITE} or L{_BIND_MODE_DIRECT}
@type mode: L{str}
- @param status: The sharing mode; L{_BIND_STATUS_INVITED} or
+ @param status: The sharing status; L{_BIND_STATUS_INVITED} or
L{_BIND_STATUS_ACCEPTED} or L{_BIND_STATUS_DECLINED} or
L{_BIND_STATUS_INVALID}.
@type mode: L{str}
@@ -2223,7 +2223,7 @@
L{_BIND_MODE_WRITE} or None to not update
@type mode: L{str}
- @param status: The sharing mode; L{_BIND_STATUS_INVITED} or
+ @param status: The sharing status; L{_BIND_STATUS_INVITED} or
L{_BIND_STATUS_ACCEPTED} or L{_BIND_STATUS_DECLINED} or
L{_BIND_STATUS_INVALID} or None to not update
@type status: L{str}
@@ -2332,30 +2332,6 @@
- @classmethod
- def _bindFor(cls, condition): #@NoSelf
- bind = cls._bindSchema
- return Select(
- [bind.BIND_MODE,
- bind.HOME_RESOURCE_ID,
- bind.RESOURCE_ID,
- bind.RESOURCE_NAME,
- bind.BIND_STATUS,
- bind.MESSAGE],
- From=bind,
- Where=condition
- )
-
-
- @classproperty
- def _sharedBindForResourceID(cls): #@NoSelf
- bind = cls._bindSchema
- return cls._bindFor((bind.RESOURCE_ID == Parameter("resourceID"))
- .And(bind.BIND_STATUS == _BIND_STATUS_ACCEPTED)
- .And(bind.BIND_MODE != _BIND_MODE_OWN)
- )
-
-
@inlineCallbacks
def asShared(self):
"""
@@ -2392,15 +2368,6 @@
result.append(new)
returnValue(result)
-
- @classproperty
- def _invitedBindForResourceID(cls): #@NoSelf
- bind = cls._bindSchema
- return cls._bindFor((bind.RESOURCE_ID == Parameter("resourceID"))
- .And(bind.BIND_STATUS != _BIND_STATUS_ACCEPTED)
- )
-
-
@inlineCallbacks
def asInvited(self):
"""
@@ -2437,9 +2404,82 @@
returnValue(result)
+ @classmethod
+ def _bindFor(cls, condition): #@NoSelf
+ bind = cls._bindSchema
+ return Select(
+ [bind.BIND_MODE,
+ bind.HOME_RESOURCE_ID,
+ bind.RESOURCE_ID,
+ bind.RESOURCE_NAME,
+ bind.BIND_STATUS,
+ bind.MESSAGE],
+ From=bind,
+ Where=condition
+ )
+ @classproperty
+ def _invitedBindForResourceID(cls): #@NoSelf
+ bind = cls._bindSchema
+ return cls._bindFor((bind.RESOURCE_ID == Parameter("resourceID"))
+ .And(bind.BIND_STATUS != _BIND_STATUS_ACCEPTED)
+ )
+
+ @classproperty
+ def _sharedBindForResourceID(cls): #@NoSelf
+ bind = cls._bindSchema
+ return cls._bindFor((bind.RESOURCE_ID == Parameter("resourceID"))
+ .And(bind.BIND_STATUS == _BIND_STATUS_ACCEPTED)
+ .And(bind.BIND_MODE != _BIND_MODE_OWN)
+ )
+
+
+ @classmethod
+ def _sharedBindForResourceIDRows(cls, txn, resourceID, homeID): #@NoSelf
+ return cls._sharedBindForResourceID.on(
+ txn, resourceID=resourceID, homeID=homeID
+ )
+
+
+ @classproperty
+ def _invitedBindForHomeID(cls): #@NoSelf
+ bind = cls._bindSchema
+ return cls._bindFor((bind.HOME_RESOURCE_ID == Parameter("homeID"))
+ .And(bind.BIND_STATUS != _BIND_STATUS_ACCEPTED))
+
+
+ @classproperty
+ def _invitedBindForNameAndHomeID(cls): #@NoSelf
+ bind = cls._bindSchema
+ return cls._bindFor((bind.RESOURCE_NAME == Parameter("name"))
+ .And(bind.HOME_RESOURCE_ID == Parameter("homeID"))
+ .And(bind.BIND_STATUS != _BIND_STATUS_ACCEPTED)
+ )
+
+
+ @classproperty
+ def _childForNameAndHomeID(cls): #@NoSelf
+ bind = cls._bindSchema
+ return cls._bindFor((bind.RESOURCE_NAME == Parameter("name"))
+ .And(bind.HOME_RESOURCE_ID == Parameter("homeID"))
+ .And(bind.BIND_STATUS == _BIND_STATUS_ACCEPTED)
+ )
+
+
+ @classproperty
+ def _bindForResourceIDAndHomeID(cls): #@NoSelf
+ """
+ DAL query that looks up home child names / bind modes by home child
+ resource ID and home resource ID.
+ """
+ bind = cls._bindSchema
+ return cls._bindFor((bind.RESOURCE_ID == Parameter("resourceID"))
+ .And(bind.HOME_RESOURCE_ID == Parameter("homeID"))
+ )
+
+
class CommonHomeChild(LoggingMixIn, FancyEqMixin, _SharedSyncLogic, HomeChildBase, SharingMixIn):
"""
Common ancestor class of AddressBooks and Calendars.
@@ -2549,13 +2589,7 @@
returnValue(names)
- @classproperty
- def _invitedBindForHomeID(cls): #@NoSelf
- bind = cls._bindSchema
- return cls._bindFor((bind.HOME_RESOURCE_ID == Parameter("homeID"))
- .And(bind.BIND_STATUS != _BIND_STATUS_ACCEPTED))
-
@classmethod
@inlineCallbacks
def listInvitedObjects(cls, home):
@@ -2725,13 +2759,6 @@
returnValue(results)
- @classproperty
- def _invitedBindForNameAndHomeID(cls): #@NoSelf
- bind = cls._bindSchema
- return cls._bindFor((bind.RESOURCE_NAME == Parameter("name"))
- .And(bind.HOME_RESOURCE_ID == Parameter("homeID"))
- .And(bind.BIND_STATUS != _BIND_STATUS_ACCEPTED)
- )
@classmethod
@@ -2787,15 +2814,6 @@
returnValue(child)
- @classproperty
- def _childForNameAndHomeID(cls): #@NoSelf
- bind = cls._bindSchema
- return cls._bindFor((bind.RESOURCE_NAME == Parameter("name"))
- .And(bind.HOME_RESOURCE_ID == Parameter("homeID"))
- .And(bind.BIND_STATUS == _BIND_STATUS_ACCEPTED)
- )
-
-
@classmethod
@inlineCallbacks
def objectWithName(cls, home, name):
@@ -2856,18 +2874,6 @@
returnValue(child)
- @classproperty
- def _bindForResourceIDAndHomeID(cls): #@NoSelf
- """
- DAL query that looks up home child names / bind modes by home child
- resource ID and home resource ID.
- """
- bind = cls._bindSchema
- return cls._bindFor((bind.RESOURCE_ID == Parameter("resourceID"))
- .And(bind.HOME_RESOURCE_ID == Parameter("homeID"))
- )
-
-
@classmethod
@inlineCallbacks
def objectWithID(cls, home, resourceID):
@@ -3576,6 +3582,13 @@
@inlineCallbacks
+ def _bumpModified(self, subtxn):
+ yield self._lockLastModifiedQuery.on(subtxn, resourceID=self._resourceID)
+ result = (yield self._changeLastModifiedQuery.on(subtxn, resourceID=self._resourceID))
+ returnValue(result)
+
+
+ @inlineCallbacks
def bumpModified(self):
"""
Bump the MODIFIED value. A possible deadlock could happen here if two or more
@@ -3589,14 +3602,8 @@
returnValue(None)
self._txn.bumpAddedForObject(self)
- @inlineCallbacks
- def _bumpModified(subtxn):
- yield self._lockLastModifiedQuery.on(subtxn, resourceID=self._resourceID)
- result = (yield self._changeLastModifiedQuery.on(subtxn, resourceID=self._resourceID))
- returnValue(result)
-
try:
- self._modified = (yield self._txn.subtransaction(_bumpModified, retries=0, failureOK=True))[0][0]
+ self._modified = (yield self._txn.subtransaction(self._bumpModified, retries=0, failureOK=True))[0][0]
queryCacher = self._txn._queryCacher
if queryCacher is not None:
Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql 2013-01-15 21:15:06 UTC (rev 10306)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql 2013-01-16 00:03:16 UTC (rev 10307)
@@ -508,7 +508,8 @@
create table ADDRESSBOOK_OBJECT_REVISIONS (
ADDRESSBOOK_HOME_RESOURCE_ID integer not null references ADDRESSBOOK_HOME,
- ADDRESSBOOK_RESOURCE_ID integer references ADDRESSBOOK,
+ -- ADDRESSBOOK_RESOURCE_ID integer references ADDRESSBOOK, -- FIXME
+ ADDRESSBOOK_RESOURCE_ID integer,
ADDRESSBOOK_NAME varchar(255) default null,
RESOURCE_NAME varchar(255),
REVISION integer default nextval('REVISION_SEQ') not null,
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130115/4e18a4f7/attachment-0001.html>
More information about the calendarserver-changes
mailing list