[CalendarServer-changes] [4049] CalendarServer/branches/users/sagen/resource-delegates-4038

source_changes at macosforge.org source_changes at macosforge.org
Tue Apr 21 06:23:56 PDT 2009


Revision: 4049
          http://trac.macosforge.org/projects/calendarserver/changeset/4049
Author:   sagen at apple.com
Date:     2009-04-21 06:23:56 -0700 (Tue, 21 Apr 2009)
Log Message:
-----------
Auto-Schedule property added; source of truth moved from directory to DB; caldav_utility can now manipulate auto-schedule.

Modified Paths:
--------------
    CalendarServer/branches/users/sagen/resource-delegates-4038/bin/caldav_utility.py
    CalendarServer/branches/users/sagen/resource-delegates-4038/calendarserver/tools/util.py
    CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/customxml.py
    CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/cachingappleopendirectory.py
    CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/cachingdirectory.py
    CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/calendaruserproxy.py
    CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/directory.py
    CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/idirectory.py
    CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/principal.py
    CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/resource.py
    CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/scheduling/processing.py

Modified: CalendarServer/branches/users/sagen/resource-delegates-4038/bin/caldav_utility.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4038/bin/caldav_utility.py	2009-04-21 00:44:45 UTC (rev 4048)
+++ CalendarServer/branches/users/sagen/resource-delegates-4038/bin/caldav_utility.py	2009-04-21 13:23:56 UTC (rev 4049)
@@ -101,6 +101,8 @@
                 "add-read-delegate=",
                 "add-write-delegate=",
                 "remove-delegate=",
+                "set-auto-schedule=",
+                "get-auto-schedule",
             ],
         )
     except GetoptError, e:
@@ -188,9 +190,20 @@
             result = (yield resource.removeDelegate(delegate, "read"))
             result = (yield resource.removeDelegate(delegate, "write"))
 
+        elif opt == "--set-auto-schedule":
+            if resource is None: abort("No current resource.")
 
+            result = (yield resource.setAutoSchedule(arg.lower() in ("true", "1")))
+
+        elif opt == "--get-auto-schedule":
+            if resource is None: abort("No current resource.")
+
+            result = (yield resource.getAutoSchedule())
+            print "Auto-Schedule: %s" % ("True" if result else "False",)
+
+
     print "Stopping reactor"
-    reactor.stop()
+    reactor.callLater(0, reactor.stop)
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -200,14 +213,10 @@
         self.resource = resource
 
     def readProperty(self, prop):
-        # fake a request
-        request = FakeRequest()
-        return self.resource.readProperty(prop, request)
+        return self.resource.readProperty(prop, FakeRequest())
 
     def writeProperty(self, prop):
-        # fake a request
-        request = FakeRequest()
-        return self.resource.writeProperty(prop, request)
+        return self.resource.writeProperty(prop, FakeRequest())
 
     def getChild(self, path):
         resource = self.resource
@@ -280,7 +289,11 @@
             result.append(str(child))
         returnValue(result)
 
+    def setAutoSchedule(self, autoSchedule):
+        return self.resource.setAutoSchedule(autoSchedule)
 
+    def getAutoSchedule(self):
+        return self.resource.getAutoSchedule()
 
     def url(self):
         return self.resource.url()
@@ -395,7 +408,7 @@
     shortNames = ("dummy",),
     fullName = "Dummy McDummerson",
     calendarUserAddresses = set(),
-    autoSchedule = False,
+    # autoSchedule = False,
 )
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Modified: CalendarServer/branches/users/sagen/resource-delegates-4038/calendarserver/tools/util.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4038/calendarserver/tools/util.py	2009-04-21 00:44:45 UTC (rev 4048)
+++ CalendarServer/branches/users/sagen/resource-delegates-4038/calendarserver/tools/util.py	2009-04-21 13:23:56 UTC (rev 4049)
@@ -105,5 +105,5 @@
     lastName = "McDummerson",
     emailAddresses = (),
     calendarUserAddresses = (),
-    autoSchedule = False,
+    # autoSchedule = False,
 )

Modified: CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/customxml.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/customxml.py	2009-04-21 00:44:45 UTC (rev 4048)
+++ CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/customxml.py	2009-04-21 13:23:56 UTC (rev 4049)
@@ -575,9 +575,17 @@
     """
     Exposes the type of a record
     """
+    namespace = calendarserver_namespace
     name = "record-type"
     protected = True
 
+class AutoSchedule (davxml.WebDAVTextElement):
+    """
+    Whether the principal automatically accepts invitations
+    """
+    namespace = calendarserver_namespace
+    name = "auto-schedule"
+
 ##
 # Extensions to davxml.ResourceType
 ##

Modified: CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/cachingappleopendirectory.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/cachingappleopendirectory.py	2009-04-21 00:44:45 UTC (rev 4048)
+++ CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/cachingappleopendirectory.py	2009-04-21 13:23:56 UTC (rev 4049)
@@ -659,7 +659,9 @@
             else:
                 memberGUIDs = ()
 
-            autoSchedule = False
+            # MOR:
+            # autoSchedule = False
+
             proxyGUIDs = ()
             readOnlyProxyGUIDs = ()
 
@@ -691,7 +693,8 @@
                 lastName              = recordLastName,
                 emailAddresses        = recordEmailAddresses,
                 calendarUserAddresses = calendarUserAddresses,
-                autoSchedule          = autoSchedule,
+                # MOR:
+                # autoSchedule          = autoSchedule,
                 enabledForCalendaring = enabledForCalendaring,
                 memberGUIDs           = memberGUIDs,
                 proxyGUIDs            = proxyGUIDs,
@@ -707,7 +710,10 @@
     def __init__(
         self, service, recordType, guid, nodeName, shortNames, authIDs,
         fullName, firstName, lastName, emailAddresses,
-        calendarUserAddresses, autoSchedule, enabledForCalendaring,
+        calendarUserAddresses,
+        # MOR:
+        # autoSchedule,
+        enabledForCalendaring,
         memberGUIDs, proxyGUIDs, readOnlyProxyGUIDs,
     ):
         super(OpenDirectoryRecord, self).__init__(
@@ -721,7 +727,8 @@
             lastName              = lastName,
             emailAddresses        = emailAddresses,
             calendarUserAddresses = calendarUserAddresses,
-            autoSchedule          = autoSchedule,
+            # MOR:
+            # autoSchedule          = autoSchedule,
             enabledForCalendaring = enabledForCalendaring,
         )
         self.nodeName = nodeName

Modified: CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/cachingdirectory.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/cachingdirectory.py	2009-04-21 00:44:45 UTC (rev 4048)
+++ CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/cachingdirectory.py	2009-04-21 13:23:56 UTC (rev 4049)
@@ -319,7 +319,9 @@
     def __init__(
         self, service, recordType, guid, shortNames=(), authIDs=set(),
         fullName=None, firstName=None, lastName=None, emailAddresses=set(),
-        calendarUserAddresses=set(), autoSchedule=False,
+        calendarUserAddresses=set(),
+        # MOR:
+        # autoSchedule=False,
         enabledForCalendaring=None, uid=None,
     ):
         super(CachingDirectoryRecord, self).__init__(
@@ -333,7 +335,8 @@
             lastName              = lastName,
             emailAddresses        = emailAddresses,
             calendarUserAddresses = calendarUserAddresses,
-            autoSchedule          = autoSchedule,
+            # MOR:
+            # autoSchedule          = autoSchedule,
             enabledForCalendaring = enabledForCalendaring,
             uid                   = uid,
         )

Modified: CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/calendaruserproxy.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/calendaruserproxy.py	2009-04-21 00:44:45 UTC (rev 4048)
+++ CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/calendaruserproxy.py	2009-04-21 13:23:56 UTC (rev 4049)
@@ -695,6 +695,8 @@
                 """
             )
 
+
+
 ##
 # Utilities
 ##

Modified: CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/directory.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/directory.py	2009-04-21 00:44:45 UTC (rev 4048)
+++ CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/directory.py	2009-04-21 13:23:56 UTC (rev 4049)
@@ -269,7 +269,10 @@
     def __init__(
         self, service, recordType, guid, shortNames=(), authIDs=set(), fullName=None,
         firstName=None, lastName=None, emailAddresses=set(),
-        calendarUserAddresses=set(), autoSchedule=False, enabledForCalendaring=None,
+        calendarUserAddresses=set(),
+        # MOR:
+        # autoSchedule=False,
+        enabledForCalendaring=None,
         uid=None,
     ):
         assert service.realmName is not None
@@ -309,7 +312,8 @@
         self.emailAddresses        = emailAddresses
         self.enabledForCalendaring = enabledForCalendaring
         self.calendarUserAddresses = calendarUserAddresses
-        self.autoSchedule          = autoSchedule
+        # MOR:
+        # self.autoSchedule          = autoSchedule
 
     def __cmp__(self, other):
         if not isinstance(other, DirectoryRecord):

Modified: CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/idirectory.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/idirectory.py	2009-04-21 00:44:45 UTC (rev 4048)
+++ CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/idirectory.py	2009-04-21 13:23:56 UTC (rev 4049)
@@ -101,7 +101,8 @@
     lastName              = Attribute("The last name of this record.")
     emailAddress          = Attribute("The email address of this record.")
     calendarUserAddresses = Attribute("A set of calendar user addresses for this record.")
-    autoSchedule          = Attribute("Principal identified by this record should automatically accept/deny meetings.")
+    # MOR:
+    # autoSchedule          = Attribute("Principal identified by this record should automatically accept/deny meetings.")
     enabledForCalendaring = Attribute("Determines whether this record should be provisioned with a calendar home.")
 
     def members():

Modified: CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/principal.py	2009-04-21 00:44:45 UTC (rev 4048)
+++ CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/directory/principal.py	2009-04-21 13:23:56 UTC (rev 4049)
@@ -837,8 +837,9 @@
 
         return addresses
 
-    def autoSchedule(self):
-        return self.record.autoSchedule
+    # MOR:
+    # def autoSchedule(self):
+    #     return self.record.autoSchedule
 
     def enabledAsOrganizer(self):
         if self.record.recordType == DirectoryService.recordType_users:

Modified: CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/resource.py	2009-04-21 00:44:45 UTC (rev 4048)
+++ CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/resource.py	2009-04-21 13:23:56 UTC (rev 4049)
@@ -27,6 +27,7 @@
     "isPseudoCalendarCollectionResource",
 ]
 
+import os
 import urllib
 
 from zope.interface import implements
@@ -36,13 +37,12 @@
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.web2 import responsecode
 from twisted.web2.dav import davxml
+from twisted.web2.dav.davxml import dav_namespace
+from twisted.web2.dav.http import ErrorResponse
 from twisted.web2.dav.idav import IDAVPrincipalCollectionResource
 from twisted.web2.dav.resource import AccessDeniedError, DAVPrincipalCollectionResource
-from twisted.web2.dav.davxml import dav_namespace
-from twisted.web2.dav.http import ErrorResponse
 from twisted.web2.dav.resource import TwistedACLInheritable
-from twisted.web2.dav.util import joinURL, parentForURL, unimplemented,\
-    normalizeURL
+from twisted.web2.dav.util import joinURL, parentForURL, unimplemented, normalizeURL
 from twisted.web2.http import HTTPError, RedirectResponse, StatusResponse, Response
 from twisted.web2.http_headers import MimeType
 from twisted.web2.iweb import IResponse
@@ -51,16 +51,18 @@
 
 import twistedcaldav
 from twistedcaldav import caldavxml, customxml
+from twistedcaldav.caldavxml import caldav_namespace
 from twistedcaldav.config import config
 from twistedcaldav.customxml import TwistedCalendarAccessProperty
+from twistedcaldav.customxml import calendarserver_namespace
 from twistedcaldav.extensions import DAVResource, DAVPrincipalResource
 from twistedcaldav.ical import Component
+from twistedcaldav.ical import Component as iComponent
+from twistedcaldav.ical import allowedComponents
 from twistedcaldav.icaldav import ICalDAVResource, ICalendarPrincipalResource
-from twistedcaldav.caldavxml import caldav_namespace
-from twistedcaldav.customxml import calendarserver_namespace
-from twistedcaldav.ical import allowedComponents
-from twistedcaldav.ical import Component as iComponent
 from twistedcaldav.log import LoggingMixIn
+from twistedcaldav.memcacher import Memcacher
+from twistedcaldav.sql import AbstractSQLDatabase, db_prefix
 
 from urlparse import urlsplit
 
@@ -828,6 +830,7 @@
         (caldav_namespace, "calendar-user-type"       ),
         (calendarserver_namespace, "calendar-proxy-read-for"  ),
         (calendarserver_namespace, "calendar-proxy-write-for" ),
+        (calendarserver_namespace, "auto-schedule" ),
     )
 
     @classmethod
@@ -898,9 +901,23 @@
                     *[davxml.HRef(principal.principalURL()) for principal in results]
                 ))
 
+            elif name == "auto-schedule":
+                autoSchedule = (yield self.getAutoSchedule())
+                returnValue(customxml.AutoSchedule("true" if autoSchedule else "false"))
+
         result = (yield super(CalendarPrincipalResource, self).readProperty(property, request))
         returnValue(result)
 
+    def writeProperty(self, property, request):
+        assert isinstance(property, davxml.WebDAVElement), (
+            "%r is not a WebDAVElement instance" % (property,)
+        )
+
+        if property.qname() == (caldav_namespace, "auto-schedule"):
+            self.setAutoSchedule(autoSchedule) # MOR: parse the value
+
+        return super(CalendarPrincipalResource, self).writeProperty(property, request)
+
     def calendarHomeURLs(self):
         if self.hasDeadProperty((caldav_namespace, "calendar-home-set")):
             home_set = self.readDeadProperty((caldav_namespace, "calendar-home-set"))
@@ -989,6 +1006,25 @@
         """
         return None
 
+    def setAutoSchedule(self, autoSchedule):
+        self._index().setAutoSchedule(self.record.guid, autoSchedule)
+
+    def getAutoSchedule(self):
+        return self._index().getAutoSchedule(self.record.guid)
+
+    def _index(self):
+        """
+        Return the SQL database for this calendar principal.
+
+        @return: the L{ResourceInfoDatabase} for the calendar principal.
+        """
+
+        # The db is located in the data root
+        self.pcollection = self.parent.parent # MOR: doesn't feel right
+        if not hasattr(self.pcollection, "resource_info_db"):
+            setattr(self.pcollection, "resource_info_db", ResourceInfoDatabase(config.DataRoot))
+        return self.pcollection.resource_info_db
+
 ##
 # Utilities
 ##
@@ -1008,3 +1044,140 @@
         return False
     else:
         return resource.isPseudoCalendarCollection()
+
+
+class ResourceInfoDatabase(AbstractSQLDatabase, LoggingMixIn):
+    """
+    A database to maintain resource (and location) information
+
+    SCHEMA:
+
+    Group Database:
+
+    ROW: GUID, AUTOSCHEDULE
+
+    """
+
+    dbType = "RESOURCEINFO"
+    dbFilename = "resourceinfo.sqlite"
+    dbOldFilename = db_prefix + "resourceinfo"
+    dbFormatVersion = "1"
+
+    class ResourceInfoDBMemcacher(Memcacher):
+
+        def setAutoSchedule(self, guid, autoSchedule):
+            print "Sending to memcache", "1" if autoSchedule else "0"
+            return self.set("resourceinfo:%s" % (str(guid),), "1" if autoSchedule else "0")
+
+        @inlineCallbacks
+        def getAutoSchedule(self, guid):
+            result = (yield self.get("resourceinfo:%s" % (str(guid),)))
+            print "Result from memcache is:", result
+            if result is not None:
+                autoSchedule = result == "1"
+            else:
+                autoSchedule = None
+            print "Therefore, getting back from memcache:", autoSchedule
+            returnValue(autoSchedule)
+
+    def __init__(self, path):
+        path = os.path.join(path, ResourceInfoDatabase.dbFilename)
+        super(ResourceInfoDatabase, self).__init__(path, True)
+
+        self._memcacher = ResourceInfoDatabase.ResourceInfoDBMemcacher("resourceInfoDB")
+
+    @inlineCallbacks
+    def setAutoSchedule(self, guid, autoSchedule):
+        """
+        Set a resource/location's auto-Schedule boolean.
+
+        @param guid: the UID of the group principal to add.
+        @param autoSchedule: boolean
+        """
+
+        # Remove what is there, then add it back.
+        self._delete_from_db(guid)
+        self._add_to_db(guid, autoSchedule)
+        self._db_commit()
+
+        # Update cache
+        _ignore = (yield self._memcacher.setAutoSchedule(guid, autoSchedule))
+
+    @inlineCallbacks
+    def getAutoSchedule(self, guid):
+        """
+        Return the auto-Schedule state for the resource/location specified by guid
+        """
+
+        # Pull from cache
+        autoSchedule = (yield self._memcacher.getAutoSchedule(guid))
+        if autoSchedule is None:
+            # Not in memcache, check local db
+            autoSchedule = self._db_value_for_sql("select AUTOSCHEDULE from RESOURCEINFO where GUID = :1", guid)
+            if autoSchedule is not None:
+                autoSchedule = autoSchedule == 1
+                result = (yield self._memcacher.setAutoSchedule(guid, autoSchedule))
+            else:
+                # Not in local db
+                # MOR: no value -- what to do, default to False?
+                autoSchedule = False
+
+        returnValue(autoSchedule)
+
+    def _add_to_db(self, guid, autoSchedule):
+        """
+        Insert the specified entry into the database.
+
+        @param guid: the guid of the resource/location
+        @param autoSchedule: a boolean
+        """
+        self._db_execute(
+            """
+            insert into RESOURCEINFO (GUID, AUTOSCHEDULE)
+            values (:1, :2)
+            """, guid, 1 if autoSchedule else 0
+        )
+
+    def _delete_from_db(self, guid):
+        """
+        Deletes the specified entry from the database.
+
+        @param guid: the guid of the resource/location to delete
+        """
+        self._db_execute("delete from RESOURCEINFO where GUID = :1", guid)
+
+    def _db_version(self):
+        """
+        @return: the schema version assigned to this index.
+        """
+        return ResourceInfoDatabase.dbFormatVersion
+
+    def _db_type(self):
+        """
+        @return: the collection type assigned to this index.
+        """
+        return ResourceInfoDatabase.dbType
+
+    def _db_init_data_tables(self, q):
+        """
+        Initialise the underlying database tables.
+        @param q:           a database cursor to use.
+        """
+
+        #
+        # RESOURCEINFO table
+        #
+        q.execute(
+            """
+            create table RESOURCEINFO (
+                GUID            text,
+                AUTOSCHEDULE    integer
+            )
+            """
+        )
+        q.execute(
+            """
+            create index RESOURCEGUIDS on RESOURCEINFO (GUID)
+            """
+        )
+

Modified: CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/scheduling/processing.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/scheduling/processing.py	2009-04-21 00:44:45 UTC (rev 4048)
+++ CalendarServer/branches/users/sagen/resource-delegates-4038/twistedcaldav/scheduling/processing.py	2009-04-21 13:23:56 UTC (rev 4049)
@@ -268,7 +268,7 @@
                 raise ImplicitProcessorException(iTIPRequestStatus.NO_USER_SUPPORT)
 
             log.debug("ImplicitProcessing - originator '%s' to recipient '%s' ignoring METHOD:REQUEST, UID: '%s' - new processed" % (self.originator.cuaddr, self.recipient.cuaddr, self.uid))
-            autoprocessed = self.recipient.principal.autoSchedule()
+            autoprocessed = self.recipient.principal.getAutoSchedule()
             new_calendar = iTipProcessing.processNewRequest(self.message, self.recipient.cuaddr, autoprocessing=autoprocessed)
             name =  md5(str(new_calendar) + str(time.time()) + default.fp.path).hexdigest() + ".ics"
             
@@ -291,7 +291,7 @@
             result = (True, autoprocessed, changes,)
         else:
             # Processing update to existing event
-            autoprocessed = self.recipient.principal.autoSchedule()
+            autoprocessed = self.recipient.principal.getAutoSchedule()
             new_calendar, props_changed, rids = iTipProcessing.processRequest(self.message, self.recipient_calendar, self.recipient.cuaddr, autoprocessing=autoprocessed)
             if new_calendar:
      
@@ -350,7 +350,7 @@
         else:
             # Need to check for auto-respond attendees. These need to suppress the inbox message
             # if the cancel is processed.
-            autoprocessed = self.recipient.principal.autoSchedule()
+            autoprocessed = self.recipient.principal.getAutoSchedule()
 
             # Check to see if this is a cancel of the entire event
             processed_message, delete_original, rids = iTipProcessing.processCancel(self.message, self.recipient_calendar, autoprocessing=autoprocessed)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090421/6f8cd5f8/attachment-0001.html>


More information about the calendarserver-changes mailing list