[CalendarServer-changes] [13236] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Apr 9 18:55:12 PDT 2014


Revision: 13236
          http://trac.calendarserver.org//changeset/13236
Author:   sagen at apple.com
Date:     2014-04-09 18:55:12 -0700 (Wed, 09 Apr 2014)
Log Message:
-----------
Adds inTransaction( ) method to the store, and now delegates.py uses that.

Modified Paths:
--------------
    CalendarServer/trunk/twistedcaldav/directory/principal.py
    CalendarServer/trunk/txdav/common/datastore/file.py
    CalendarServer/trunk/txdav/common/datastore/sql.py
    CalendarServer/trunk/txdav/common/datastore/test/test_sql.py
    CalendarServer/trunk/txdav/who/delegates.py
    CalendarServer/trunk/txdav/who/util.py

Modified: CalendarServer/trunk/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/principal.py	2014-04-10 01:43:23 UTC (rev 13235)
+++ CalendarServer/trunk/twistedcaldav/directory/principal.py	2014-04-10 01:55:12 UTC (rev 13236)
@@ -484,7 +484,7 @@
                 for record in (
                     yield self.directory.recordsWithRecordType(self.recordType)
                 ):
-                    for shortName in record.shortNames:
+                    for shortName in getattr(record, "shortNames", []):
                         children.append(shortName)
             except AttributeError:
                 log.warn("Cannot list children of record type {rt}",
@@ -638,19 +638,17 @@
             emailAddresses = record.emailAddresses
         except AttributeError:
             emailAddresses = []
+        try:
+            shortNames = record.shortNames
+        except AttributeError:
+            shortNames = []
         return tag.fillSlots(
             directoryGUID=str(record.service.guid),
             realm=record.service.realmName.encode("utf-8"),
             principalGUID=guid,
             recordType=record.service.recordTypeToOldName(record.recordType),
-            shortNames=",".join([n.encode("utf-8") for n in record.shortNames]),
-            # MOVE2WHO: need this?
-            # securityIDs=",".join(record.authIDs),
+            shortNames=",".join([n.encode("utf-8") for n in shortNames]),
             fullName=record.displayName.encode("utf-8"),
-            # MOVE2WHO: need this?
-            # firstName=str(record.firstName),
-            # MOVE2WHO: need this?
-            # lastName=str(record.lastName),
             emailAddresses=formatList(emailAddresses),
             principalUID=str(self.resource.principalUID()),
             principalURL=formatLink(self.resource.principalURL()),
@@ -815,12 +813,12 @@
                 record.service.recordTypeToOldName(record.recordType),
                 quote(shortName.encode("utf-8"))
             ) + slash
-            for shortName in record.shortNames
+            for shortName in getattr(record, "shortNames", [])
         ])
 
 
     def __str__(self):
-        return "(%s)%s" % (self.record.recordType, self.record.shortNames[0])
+        return "(%s)%s" % (self.record.recordType, self.record.uid)
 
 
     def __eq__(self, other):

Modified: CalendarServer/trunk/txdav/common/datastore/file.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/file.py	2014-04-10 01:43:23 UTC (rev 13235)
+++ CalendarServer/trunk/txdav/common/datastore/file.py	2014-04-10 01:55:12 UTC (rev 13236)
@@ -31,6 +31,7 @@
 from twisted.internet.defer import succeed, inlineCallbacks, returnValue
 from twisted.python.util import FancyEqMixin
 from twisted.python import hashlib
+from twisted.python.failure import Failure
 
 from twistedcaldav import customxml
 from twistedcaldav.customxml import NotificationType
@@ -182,6 +183,41 @@
 
 
     @inlineCallbacks
+    def inTransaction(self, label, operation, transactionCreator=None):
+        """
+        Perform the given operation in a transaction, committing or aborting as
+        required.
+
+        @param label: the label to pass to the transaction creator
+
+        @param operation: a 1-arg callable that takes an L{IAsyncTransaction} and
+            returns a value.
+
+        @param transactionCreator: a 1-arg callable that takes a "label" arg and
+            returns a transaction
+
+        @return: a L{Deferred} that fires with C{operation}'s result or fails with
+            its error, unless there is an error creating, aborting or committing
+            the transaction.
+        """
+
+        if transactionCreator is None:
+            txn = self.newTransaction()
+        else:
+            txn = transactionCreator(label=label)
+
+        try:
+            result = yield operation(txn)
+        except:
+            f = Failure()
+            yield txn.abort()
+            returnValue(f)
+        else:
+            yield txn.commit()
+            returnValue(result)
+
+
+    @inlineCallbacks
     def _withEachHomeDo(self, enumerator, action, batchSize):
         """
         Implementation of L{ICalendarStore.withEachCalendarHomeDo} and

Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py	2014-04-10 01:43:23 UTC (rev 13235)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py	2014-04-10 01:55:12 UTC (rev 13236)
@@ -293,6 +293,41 @@
         return txn
 
 
+    @inlineCallbacks
+    def inTransaction(self, label, operation, transactionCreator=None):
+        """
+        Perform the given operation in a transaction, committing or aborting as
+        required.
+
+        @param label: the label to pass to the transaction creator
+
+        @param operation: a 1-arg callable that takes an L{IAsyncTransaction} and
+            returns a value.
+
+        @param transactionCreator: a 1-arg callable that takes a "label" arg and
+            returns a transaction
+
+        @return: a L{Deferred} that fires with C{operation}'s result or fails with
+            its error, unless there is an error creating, aborting or committing
+            the transaction.
+        """
+
+        if transactionCreator is None:
+            txn = self.newTransaction()
+        else:
+            txn = transactionCreator(label=label)
+
+        try:
+            result = yield operation(txn)
+        except:
+            f = Failure()
+            yield txn.abort()
+            returnValue(f)
+        else:
+            yield txn.commit()
+            returnValue(result)
+
+
     def setMigrating(self, state):
         """
         Set the "migrating" state

Modified: CalendarServer/trunk/txdav/common/datastore/test/test_sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/test/test_sql.py	2014-04-10 01:43:23 UTC (rev 13235)
+++ CalendarServer/trunk/txdav/common/datastore/test/test_sql.py	2014-04-10 01:55:12 UTC (rev 13236)
@@ -21,7 +21,7 @@
 from twext.enterprise.dal.syntax import Select
 from twext.enterprise.dal.syntax import Insert
 
-from twisted.internet.defer import inlineCallbacks, returnValue
+from twisted.internet.defer import inlineCallbacks, returnValue, succeed
 from twisted.internet.task import Clock
 from twisted.trial.unittest import TestCase
 from twisted.internet.defer import Deferred
@@ -433,3 +433,50 @@
         yield fixUUIDNormalization(self.storeUnderTest())
         self.assertEqual((yield self.allHomeUIDs(schema.ADDRESSBOOK_HOME)),
                          [[normalizedUID]])
+
+
+    @inlineCallbacks
+    def test_inTransaction(self):
+        """
+        Make sure a successful operation commits the transaction while an
+        unsuccessful operation (raised an exception) aborts the transaction.
+        """
+
+        store = self.storeUnderTest()
+
+        def txnCreator(label):
+            self.txn = StubTransaction(label)
+            return self.txn
+
+        def goodOperation(txn):
+            return succeed(None)
+
+        def badOperation(txn):
+            1 / 0
+            return succeed(None)
+
+        yield store.inTransaction("good", goodOperation, txnCreator)
+        self.assertEquals(self.txn.action, "committed")
+
+        try:
+            yield store.inTransaction("bad", badOperation, txnCreator)
+        except:
+            pass
+        self.assertEquals(self.txn.action, "aborted")
+
+
+
+class StubTransaction(object):
+
+    def __init__(self, label):
+        self.label = label
+        self.action = None
+
+    def commit(self):
+        self.action = "committed"
+        return succeed(None)
+
+    def abort(self):
+        self.action = "aborted"
+        return succeed(None)
+

Modified: CalendarServer/trunk/txdav/who/delegates.py
===================================================================
--- CalendarServer/trunk/txdav/who/delegates.py	2014-04-10 01:43:23 UTC (rev 13235)
+++ CalendarServer/trunk/txdav/who/delegates.py	2014-04-10 01:55:12 UTC (rev 13236)
@@ -68,21 +68,26 @@
         """
         parentUID, _ignore_proxyType = self.uid.split(u"#")
 
-        txn = self.service._store.newTransaction(label="DirectoryRecord.members")
+        @inlineCallbacks
+        def _members(txn):
+            if self.recordType in (
+                RecordType.readDelegateGroup, RecordType.writeDelegateGroup
+            ):  # Members are delegates of this record
+                readWrite = (self.recordType is RecordType.writeDelegateGroup)
+                delegateUIDs = (
+                    yield txn.delegates(parentUID, readWrite, expanded=expanded)
+                )
 
-        if self.recordType in (
-            RecordType.readDelegateGroup, RecordType.writeDelegateGroup
-        ):  # Members are delegates of this record
-            readWrite = (self.recordType is RecordType.writeDelegateGroup)
-            delegateUIDs = (
-                yield txn.delegates(parentUID, readWrite, expanded=expanded)
-            )
+            else:  # Members have delegated to this record
+                readWrite = (self.recordType is RecordType.writeDelegatorGroup)
+                delegateUIDs = (
+                    yield txn.delegators(parentUID, readWrite)
+                )
+            returnValue(delegateUIDs)
 
-        else:  # Members have delegated to this record
-            readWrite = (self.recordType is RecordType.writeDelegatorGroup)
-            delegateUIDs = (
-                yield txn.delegators(parentUID, readWrite)
-            )
+        delegateUIDs = yield self.service._store.inTransaction(
+            "DirectoryRecord.members", _members
+        )
 
         records = []
         for uid in delegateUIDs:
@@ -90,7 +95,6 @@
                 record = yield self.service._masterDirectory.recordWithUID(uid)
                 if record is not None:
                     records.append(record)
-        yield txn.commit()
 
         returnValue(records)
 
@@ -117,22 +121,24 @@
             m=[r.uid for r in memberRecords]
         )
 
-        txn = self.service._store.newTransaction(label="DirectoryRecord.setMembers")
+        @inlineCallbacks
+        def _setMembers(txn):
+            yield txn.removeDelegates(parentUID, readWrite)
+            yield txn.removeDelegateGroups(parentUID, readWrite)
 
-        yield txn.removeDelegates(parentUID, readWrite)
-        yield txn.removeDelegateGroups(parentUID, readWrite)
+            delegator = (
+                yield self.service._masterDirectory.recordWithUID(parentUID)
+            )
 
-        delegator = (
-            yield self.service._masterDirectory.recordWithUID(parentUID)
+            for delegate in memberRecords:
+                yield addDelegate(txn, delegator, delegate, readWrite)
+
+        yield self.service._store.inTransaction(
+            "DirectoryRecord.setMembers", _setMembers
         )
 
-        for delegate in memberRecords:
-            yield addDelegate(txn, delegator, delegate, readWrite)
 
-        yield txn.commit()
 
-
-
 def recordTypeToProxyType(recordType):
     return {
         RecordType.readDelegateGroup: "calendar-proxy-read",

Modified: CalendarServer/trunk/txdav/who/util.py
===================================================================
--- CalendarServer/trunk/txdav/who/util.py	2014-04-10 01:43:23 UTC (rev 13235)
+++ CalendarServer/trunk/txdav/who/util.py	2014-04-10 01:55:12 UTC (rev 13236)
@@ -106,7 +106,6 @@
                 params.rdnSchema.base,
                 credentials=creds,
                 fieldNameToAttributesMap=MappingProxyType({
-                    # FieldName.dn: (LDAPAttribute.dn.value,),
                     BaseFieldName.uid: ("apple-generateduid",),
                     BaseFieldName.guid: ("apple-generateduid",),
                     BaseFieldName.shortNames: (LDAPAttribute.uid.value,),
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140409/c8ffe52e/attachment-0001.html>


More information about the calendarserver-changes mailing list