[prev in list] [next in list] [prev in thread] [next in thread] 

List:       calendarserver-changes
Subject:    [CalendarServer-changes] [7384]
From:       source_changes () macosforge ! org
Date:       2011-04-29 17:56:33
Message-ID: 20110429175634.8316019B9DAD () lists ! macosforge ! org
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


Revision: 7384
          http://trac.macosforge.org/projects/calendarserver/changeset/7384
Author:   sagen@apple.com
Date:     2011-04-29 10:56:32 -0700 (Fri, 29 Apr 2011)
Log Message:
-----------
Applying inbox fix to branch

Modified Paths:
--------------
    CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/__init__.py
  CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/task.py
    CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/test/__init__.py
  CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/test/test_task.py
  CalendarServer/branches/users/sagen/gm2submission/calendarserver/tap/caldav.py
    CalendarServer/branches/users/sagen/gm2submission/twisted/plugins/caldav.py
    CalendarServer/branches/users/sagen/gm2submission/twistedcaldav/test/test_upgrade.py
  CalendarServer/branches/users/sagen/gm2submission/twistedcaldav/upgrade.py

Modified: CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/__init__.py
 ===================================================================
--- CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/__init__.py	2011-04-29 \
                17:35:22 UTC (rev 7383)
+++ CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/__init__.py	2011-04-29 \
17:56:32 UTC (rev 7384) @@ -1,19 +0,0 @@
-##
-# Copyright (c) 2005-2009 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-"""
-CalendarServer "sidecar" processes
-"""

Modified: CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/task.py
 ===================================================================
--- CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/task.py	2011-04-29 \
                17:35:22 UTC (rev 7383)
+++ CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/task.py	2011-04-29 \
17:56:32 UTC (rev 7384) @@ -1,342 +0,0 @@
-# Copyright (c) 2005-2010 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-from __future__ import with_statement
-
-__all__ = [
-    "CalDAVTaskService",
-    "CalDAVTaskServiceMaker",
-    "CalDAVTaskOptions",
-    "Task",
-]
-
-import os
-from datetime import date, timedelta
-
-from zope.interface import implements
-
-from twisted.application.service import MultiService, Service, IServiceMaker
-from twisted.internet.defer import DeferredList, inlineCallbacks, returnValue
-from twisted.internet.reactor import callLater
-from twisted.plugin import IPlugin
-from twisted.python.usage import Options, UsageError
-
-from twext.python.log import Logger, LoggingMixIn
-from twext.python.log import logLevelForNamespace, setLogLevelForNamespace
-
-from twistedcaldav.config import config
-from twistedcaldav.stdconfig import DEFAULT_CONFIG, DEFAULT_CONFIG_FILE
-from twistedcaldav.ical import Component
-from twistedcaldav.scheduling.cuaddress import LocalCalendarUser
-from twistedcaldav.scheduling.scheduler import DirectScheduler
-
-from calendarserver.tap.util import getRootResource, FakeRequest
-from calendarserver.tools.purge import purgeOldEvents
-
-log = Logger()
-
-@inlineCallbacks
-def processInboxItem(rootResource, directory, inboxFile, inboxItemFile, uuid):
-    log.debug("Processing inbox item %s" % (inboxItemFile,))
-
-    principals = rootResource.getChild("principals")
-    ownerPrincipal = principals.principalForUID(uuid)
-    cua = "urn:uuid:%s" % (uuid,)
-    owner = LocalCalendarUser(cua, ownerPrincipal,
-        inboxFile, ownerPrincipal.scheduleInboxURL())
-
-    data = inboxItemFile.iCalendarText()
-    calendar = Component.fromString(data)
-    try:
-        method = calendar.propertyValue("METHOD")
-    except ValueError:
-        returnValue(None)
-
-    if method == "REPLY":
-        # originator is attendee sending reply
-        originator = calendar.getAttendees()[0]
-    else:
-        # originator is the organizer
-        originator = calendar.getOrganizer()
-
-    originatorPrincipal = principals.principalForCalendarUserAddress(originator)
-    originator = LocalCalendarUser(originator, originatorPrincipal)
-    recipients = (owner,)
-    scheduler = DirectScheduler(FakeRequest(rootResource, "PUT"), inboxItemFile)
-    yield scheduler.doSchedulingViaPUT(originator, recipients, calendar, \
                internal_request=False)
-
-    if os.path.exists(inboxItemFile.fp.path):
-        os.remove(inboxItemFile.fp.path)
-
-
-
-class Task(object):
-
-    def __init__(self, service, fileName):
-        self.service = service
-        self.taskName = fileName.split(".")[0]
-        self.taskFile = os.path.join(self.service.processingDir, fileName)
-
-    @inlineCallbacks
-    def run(self):
-        methodName = "task_%s" % (self.taskName,)
-        method = getattr(self, methodName, None)
-        if method:
-            try:
-                log.warn("Running task '%s'" % (self.taskName))
-                yield method()
-                log.warn("Completed task '%s'" % (self.taskName))
-            except Exception, e:
-                log.error("Failed task '%s' (%s)" % (self.taskName, e))
-                os.remove(self.taskFile)
-                raise
-        else:
-            log.error("Unknown task requested: '%s'" % (self.taskName))
-            os.remove(self.taskFile)
-            returnValue(None)
-
-    @inlineCallbacks
-    def task_scheduleinboxes(self):
-
-        calendars = self.service.root.getChild("calendars")
-        uidDir = calendars.getChild("__uids__")
-
-        inboxItems = set()
-        with open(self.taskFile) as input:
-            for inboxItem in input:
-                inboxItem = inboxItem.strip()
-                inboxItems.add(inboxItem)
-
-        for inboxItem in list(inboxItems):
-            log.info("Processing inbox item: %s" % (inboxItem,))
-            ignore, uuid, ignore, fileName = inboxItem.rsplit("/", 3)
-
-            homeFile = uidDir.getChild(uuid)
-            if not homeFile:
-                continue
-
-            inboxFile = homeFile.getChild("inbox")
-            if not inboxFile:
-                continue
-
-            inboxItemFile = inboxFile.getChild(fileName)
-
-            yield processInboxItem(
-                self.service.root,
-                self.service.directory,
-                inboxFile,
-                inboxItemFile,
-                uuid
-            )
-            inboxItems.remove(inboxItem)
-
-            # Rewrite the task file in case we exit before we're done
-            with open(self.taskFile + ".tmp", "w") as output:
-                for inboxItem in inboxItems:
-                    output.write("%s\n" % (inboxItem,))
-            os.rename(self.taskFile + ".tmp", self.taskFile)
-
-        os.remove(self.taskFile)
-
-
-    @inlineCallbacks
-    def task_purgeoldevents(self):
-
-        with open(self.taskFile) as input:
-            try:
-                value = input.read().strip()
-                days = int(value)
-            except ValueError:
-                log.error("Illegal value for purge days: %s" % (value,))
-            else:
-                cutoff = (date.today() -
-                    timedelta(days=days)).strftime("%Y%m%dT000000Z")
-                count = (yield purgeOldEvents(self.service.directory,
-                    self.service.root, cutoff))
-                log.info("Purged %d events" % (count,))
-
-        os.remove(self.taskFile)
-
-
-class CalDAVTaskService(Service):
-
-    def __init__(self, root):
-        self.root = root
-        self.directory = root.directory
-        self.seconds = 30 # How often to check for new tasks in incomingDir
-        self.taskDir = os.path.join(config.DataRoot, "tasks")
-        # New task files are placed into "incoming"
-        self.incomingDir = os.path.join(self.taskDir, "incoming")
-        # Task files get moved into "processing" and then removed when complete
-        self.processingDir = os.path.join(self.taskDir, "processing")
-
-    def startService(self):
-        log.info("Starting task service")
-
-        if not os.path.exists(self.taskDir):
-            os.mkdir(self.taskDir)
-        if not os.path.exists(self.incomingDir):
-            os.mkdir(self.incomingDir)
-        if not os.path.exists(self.processingDir):
-            os.mkdir(self.processingDir)
-
-        callLater(self.seconds, self.periodic, first=True)
-
-
-    def periodic(self, first=False):
-        # log.debug("Checking for tasks")
-
-        deferreds = []
-
-        try:
-            if first:
-                # check the processing directory to see if there are any tasks
-                # that didn't complete during the last server run; start those
-                for fileName in os.listdir(self.processingDir):
-                    if fileName.endswith(".task"):
-                        log.debug("Restarting old task: %s" % (fileName,))
-                        deferreds.append(Task(self, fileName).run())
-
-            for fileName in os.listdir(self.incomingDir):
-                if fileName.endswith(".task"):
-                    log.debug("Found new task: %s" % (fileName,))
-                    os.rename(os.path.join(self.incomingDir, fileName),
-                        os.path.join(self.processingDir, fileName))
-                    deferreds.append(Task(self, fileName).run())
-
-        finally:
-            callLater(self.seconds, self.periodic)
-
-        return DeferredList(deferreds)
-
-
-
-class CalDAVTaskOptions(Options):
-    optParameters = [[
-        "config", "f", DEFAULT_CONFIG_FILE, "Path to configuration file."
-    ]]
-
-    def __init__(self, *args, **kwargs):
-        super(CalDAVTaskOptions, self).__init__(*args, **kwargs)
-
-        self.overrides = {}
-
-    def _coerceOption(self, configDict, key, value):
-        """
-        Coerce the given C{val} to type of C{configDict[key]}
-        """
-        if key in configDict:
-            if isinstance(configDict[key], bool):
-                value = value == "True"
-
-            elif isinstance(configDict[key], (int, float, long)):
-                value = type(configDict[key])(value)
-
-            elif isinstance(configDict[key], (list, tuple)):
-                value = value.split(',')
-
-            elif isinstance(configDict[key], dict):
-                raise UsageError(
-                    "Dict options not supported on the command line"
-                )
-
-            elif value == 'None':
-                value = None
-
-        return value
-
-    def _setOverride(self, configDict, path, value, overrideDict):
-        """
-        Set the value at path in configDict
-        """
-        key = path[0]
-
-        if len(path) == 1:
-            overrideDict[key] = self._coerceOption(configDict, key, value)
-            return
-
-        if key in configDict:
-            if not isinstance(configDict[key], dict):
-                raise UsageError(
-                    "Found intermediate path element that is not a dictionary"
-                )
-
-            if key not in overrideDict:
-                overrideDict[key] = {}
-
-            self._setOverride(
-                configDict[key], path[1:],
-                value, overrideDict[key]
-            )
-
-
-    def opt_option(self, option):
-        """
-        Set an option to override a value in the config file. True, False, int,
-        and float options are supported, as well as comma seperated lists. Only
-        one option may be given for each --option flag, however multiple
-        --option flags may be specified.
-        """
-
-        if "=" in option:
-            path, value = option.split('=')
-            self._setOverride(
-                DEFAULT_CONFIG,
-                path.split('/'),
-                value,
-                self.overrides
-            )
-        else:
-            self.opt_option('%s=True' % (option,))
-
-    opt_o = opt_option
-
-    def postOptions(self):
-        config.load(self['config'])
-        config.updateDefaults(self.overrides)
-        self.parent['pidfile'] = None
-
-
-class CalDAVTaskServiceMaker (LoggingMixIn):
-    implements(IPlugin, IServiceMaker)
-
-    tapname = "caldav_task"
-    description = "Calendar Server Task Process"
-    options = CalDAVTaskOptions
-
-    def makeService(self, options):
-
-        svc = MultiService()
-        #
-        # The task sidecar doesn't care about system SACLs
-        #
-        config.EnableSACLs = False
-
-        #
-        # Change default log level to "info" as its useful to have
-        # that during startup
-        #
-        oldLogLevel = logLevelForNamespace(None)
-        setLogLevelForNamespace(None, "info")
-
-        rootResource = getRootResource(config, svc)
-
-        CalDAVTaskService(rootResource).setServiceParent(svc)
-
-        # Change log level back to what it was before
-        setLogLevelForNamespace(None, oldLogLevel)
-
-        return svc
-

Modified: CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/test/__init__.py
 ===================================================================
--- CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/test/__init__.py	2011-04-29 \
                17:35:22 UTC (rev 7383)
+++ CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/test/__init__.py	2011-04-29 \
17:56:32 UTC (rev 7384) @@ -1,15 +0,0 @@
-##
-# Copyright (c) 2010 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##

Modified: CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/test/test_task.py
 ===================================================================
--- CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/test/test_task.py	2011-04-29 \
                17:35:22 UTC (rev 7383)
+++ CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/test/test_task.py	2011-04-29 \
17:56:32 UTC (rev 7384) @@ -1,216 +0,0 @@
-##
-# Copyright (c) 2009 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-import os, zlib
-
-from calendarserver.sidecar.task import CalDAVTaskServiceMaker, CalDAVTaskOptions, \
                Task
-from os.path import dirname, abspath
-from twext.python.plistlib import writePlist
-from twisted.python.usage import Options
-from twistedcaldav.config import config, ConfigDict
-from twistedcaldav.stdconfig import DEFAULT_CONFIG
-from twistedcaldav.test.util import TestCase, todo
-from twisted.internet.defer import inlineCallbacks
-
-# Points to top of source tree.
-sourceRoot = dirname(dirname(dirname(dirname(abspath(__file__)))))
-
-
-# TODO: update or delete task sidecar
-class CalDAVTaskServiceTest(object): # TestCase):
-    """
-    Test various parameters of our usage.Options subclass
-    """
-    def setUp(self):
-        """
-        Set up our options object, giving it a parent, and forcing the
-        global config to be loaded from defaults.
-        """
-        TestCase.setUp(self)
-        self.options = CalDAVTaskOptions()
-        self.options.parent = Options()
-        self.options.parent["uid"] = 0
-        self.options.parent["gid"] = 0
-        self.options.parent["nodaemon"] = False
-
-        self.config = ConfigDict(DEFAULT_CONFIG)
-
-        accountsFile = os.path.join(sourceRoot, \
                "twistedcaldav/directory/test/accounts.xml")
-        self.config["DirectoryService"] = {
-            "params": {"xmlFile": accountsFile},
-            "type": "twistedcaldav.directory.xmlfile.XMLDirectoryService"
-        }
-
-        self.config.DocumentRoot   = self.mktemp()
-        self.config.DataRoot       = self.mktemp()
-        self.config.ProcessType    = "Single"
-        self.config.Memcached.ClientEnabled = False
-        self.config.Memcached.ServerEnabled = False
-
-
-        pemFile = os.path.join(sourceRoot, "twistedcaldav/test/data/server.pem")
-        self.config.SSLPrivateKey = pemFile
-        self.config.SSLCertificate = pemFile
-
-        os.mkdir(self.config.DocumentRoot)
-        os.mkdir(self.config.DataRoot)
-
-        self.configFile = self.mktemp()
-
-        self.writeConfig()
-
-    def writeConfig(self):
-        """
-        Flush self.config out to self.configFile
-        """
-        writePlist(self.config, self.configFile)
-
-    def tearDown(self):
-        config.setDefaults(DEFAULT_CONFIG)
-        config.reload()
-
-    def makeService(self):
-        self.options.parseOptions(["-f", self.configFile])
-        return CalDAVTaskServiceMaker().makeService(self.options)
-
-    @todo("FIXME: fix after new store changes")
-    @inlineCallbacks
-    def test_taskService(self):
-        service = self.makeService()
-
-        structure = {
-            "calendars" : {
-                "__uids__" : {
-                    "64" : {
-                        "23" : {
-                            "6423F94A-6B76-4A3A-815B-D52CFD77935D" : {
-                                "calendar": {
-                                    "@xattrs" :
-                                    {
-                                        "WebDAV:{DAV:}resourcetype" : \
zlib.compress("<?xml version='1.0' encoding='UTF-8'?>\r\n<resourcetype \
xmlns='DAV:'>\r\n<collection/>\r\n<calendar \
                xmlns='urn:ietf:params:xml:ns:caldav'/>\r\n</resourcetype>\r\n"),
-                                    },
-                                },
-                                "inbox": {
-                                    "unprocessed.ics": {
-                                        "@contents" : unprocessed,
-                                    }
-                                },
-                            }
-                        }
-                    }
-                }
-            },
-        }
-
-        self.createHierarchy(structure, root=self.config.DocumentRoot)
-
-        structure = {
-            "tasks" : {
-                "incoming" : { },
-                "processing" : {
-                    "scheduleinboxes.task" : {
-                        "@contents" : os.path.join(
-                            self.config.DocumentRoot,
-                            "calendars",
-                            "__uids__",
-                            "64",
-                            "23",
-                            "6423F94A-6B76-4A3A-815B-D52CFD77935D",
-                            "inbox",
-                            "unprocessed.ics"
-                        ),
-                    },
-                },
-            },
-        }
-
-        self.createHierarchy(structure, root=self.config.DataRoot)
-
-        task = Task(service, "scheduleinboxes.task")
-        yield task.run()
-
-        # Aftwards we want to see a .ics file in calendar and inbox
-        structure = {
-            "calendars" : {
-                "__uids__" : {
-                    "64" : {
-                        "23" : {
-                            "6423F94A-6B76-4A3A-815B-D52CFD77935D" : {
-                                "calendar": {
-                                    ".db.sqlite" : {
-                                        "@contents" : None,
-                                    },
-                                    "*.ics": {
-                                        "@contents" : None,
-                                    },
-                                },
-                                "inbox": {
-                                    ".db.sqlite" : {
-                                        "@contents" : None,
-                                    },
-                                    "*.ics": {
-                                        "@contents" : None,
-                                    },
-                                },
-                            }
-                        }
-                    }
-                }
-            },
-        }
-        self.assertTrue(self.verifyHierarchy(self.config.DocumentRoot, structure))
-
-unprocessed = """BEGIN:VCALENDAR
-VERSION:2.0
-CALSCALE:GREGORIAN
-METHOD:REQUEST
-PRODID:-//Apple Inc.//iCal 4.0.1//EN
-BEGIN:VTIMEZONE
-TZID:US/Pacific
-BEGIN:STANDARD
-DTSTART:20071104T020000
-RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
-TZNAME:PST
-TZOFFSETFROM:-0700
-TZOFFSETTO:-0800
-END:STANDARD
-BEGIN:DAYLIGHT
-DTSTART:20070311T020000
-RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
-TZNAME:PDT
-TZOFFSETFROM:-0800
-TZOFFSETTO:-0700
-END:DAYLIGHT
-END:VTIMEZONE
-BEGIN:VEVENT
-UID:A40F4892-B40F-4C0F-B8D0-F4EB2C97F4B9
-DTSTART;TZID=US/Pacific:20091209T120000
-DTEND;TZID=US/Pacific:20091209T130000
-ATTENDEE;CN=Wilfredo Sanchez;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=N
- EEDS-ACTION;EMAIL=wsanchez@example.com;RSVP=TRUE:/principals/__uids__/6423F94
- A-6B76-4A3A-815B-D52CFD77935D/
-ATTENDEE;CUTYPE=INDIVIDUAL;CN=Morgen Sagen;PARTSTAT=ACCEPTED:mailto:sagen@exam
- ple.com
-CREATED:20091209T183541Z
-DTSTAMP:20091209T183612Z
-ORGANIZER;CN=Morgen Sagen:mailto:sagen@example.com
-SEQUENCE:6
-SUMMARY:Test
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR
-""".replace("\n", "\r\n")
-

Modified: CalendarServer/branches/users/sagen/gm2submission/calendarserver/tap/caldav.py
 ===================================================================
--- CalendarServer/branches/users/sagen/gm2submission/calendarserver/tap/caldav.py	2011-04-29 \
                17:35:22 UTC (rev 7383)
+++ CalendarServer/branches/users/sagen/gm2submission/calendarserver/tap/caldav.py	2011-04-29 \
17:56:32 UTC (rev 7384) @@ -69,7 +69,7 @@
 from twistedcaldav.mail import IMIPReplyInboxResource
 from twistedcaldav import memcachepool
 from twistedcaldav.stdconfig import DEFAULT_CONFIG, DEFAULT_CONFIG_FILE
-from twistedcaldav.upgrade import UpgradeFileSystemFormatService
+from twistedcaldav.upgrade import UpgradeFileSystemFormatService, \
PostDBImportService  
 from calendarserver.tap.util import pgServiceFromConfig
 
@@ -429,7 +429,6 @@
     L{DelayedStartupProcessMonitor}:
 
         - regular slave processes (CalDAV workers)
-        - task sidecar
         - notifier
         - mail gateway
     """
@@ -506,27 +505,8 @@
             self.monitor.addProcess("mailgateway", mailGatewayArgv,
                                env=PARENT_ENVIRONMENT)
 
-        self.maker.log_info("Adding task service")
-        taskArgv = [
-            sys.executable,
-            sys.argv[0],
-        ]
-        if config.UserName:
-            taskArgv.extend(("-u", config.UserName))
-        if config.GroupName:
-            taskArgv.extend(("-g", config.GroupName))
-        taskArgv.extend((
-            "--reactor=%s" % (config.Twisted.reactor,),
-            "-n", "caldav_task",
-            "-f", self.configPath,
-        ))
 
-        self.monitor.addProcess(
-            "caldav_task", taskArgv, env=PARENT_ENVIRONMENT
-        )
 
-
-
 class CalDAVServiceMaker (LoggingMixIn):
     implements(IPlugin, IServiceMaker)
 
@@ -982,7 +962,8 @@
             mainService = createMainService(cp, store)
             upgradeSvc = UpgradeFileSystemFormatService(config,
                 UpgradeToDatabaseService.wrapService(
-                    CachingFilePath(config.DocumentRoot), mainService,
+                    CachingFilePath(config.DocumentRoot),
+                    PostDBImportService(config, store, mainService),
                     store, uid=uid, gid=gid
                 )
             )

Modified: CalendarServer/branches/users/sagen/gm2submission/twisted/plugins/caldav.py
===================================================================
--- CalendarServer/branches/users/sagen/gm2submission/twisted/plugins/caldav.py	2011-04-29 \
                17:35:22 UTC (rev 7383)
+++ CalendarServer/branches/users/sagen/gm2submission/twisted/plugins/caldav.py	2011-04-29 \
17:56:32 UTC (rev 7384) @@ -50,6 +50,5 @@
 
 
 TwistedCalDAV     = TAP("calendarserver.tap.caldav.CalDAVServiceMaker")
-CalDAVTask        = TAP("calendarserver.sidecar.task.CalDAVTaskServiceMaker")
 CalDAVNotifier    = TAP("twistedcaldav.notify.NotificationServiceMaker")
 CalDAVMailGateway = TAP("twistedcaldav.mail.MailGatewayServiceMaker")

Modified: CalendarServer/branches/users/sagen/gm2submission/twistedcaldav/test/test_upgrade.py
 ===================================================================
--- CalendarServer/branches/users/sagen/gm2submission/twistedcaldav/test/test_upgrade.py	2011-04-29 \
                17:35:22 UTC (rev 7383)
+++ CalendarServer/branches/users/sagen/gm2submission/twistedcaldav/test/test_upgrade.py	2011-04-29 \
17:56:32 UTC (rev 7384) @@ -318,7 +318,6 @@
             },
             MailGatewayTokensDatabase.dbFilename : { "@contents" : None },
             "%s-journal" % (MailGatewayTokensDatabase.dbFilename,) : { "@contents" : \
                None },
-            "tasks" : {"incoming" : {}}
         }
 
         (yield self.verifyDirectoryComparison(before, after))
@@ -385,12 +384,6 @@
         }
 
         after = {
-            "tasks" :
-            {
-                "incoming" :
-                {
-                },
-            },
             ".calendarserver_version" :
             {
                 "@contents" : "2",
@@ -505,12 +498,6 @@
                 {
                 },
             },
-            "tasks" :
-            {
-                "incoming" :
-                {
-                },
-            },
             ".calendarserver_version" :
             {
                 "@contents" : "2",
@@ -597,12 +584,6 @@
                 {
                 },
             },
-            "tasks" :
-            {
-                "incoming" :
-                {
-                },
-            },
             ".calendarserver_version" :
             {
                 "@contents" : "2",
@@ -691,12 +672,6 @@
             {
                 "@contents" : "",
             },
-            "tasks" :
-            {
-                "incoming" :
-                {
-                },
-            },
             ".calendarserver_version" :
             {
                 "@contents" : "2",
@@ -770,12 +745,6 @@
         }
 
         after = {
-            "tasks" :
-            {
-                "incoming" :
-                {
-                },
-            },
             ".calendarserver_version" :
             {
                 "@contents" : "2",
@@ -886,12 +855,6 @@
         }
 
         after = {
-            "tasks" :
-            {
-                "incoming" :
-                {
-                },
-            },
             ".calendarserver_version" :
             {
                 "@contents" : "2",
@@ -1006,12 +969,6 @@
         }
 
         after = {
-            "tasks" :
-            {
-                "incoming" :
-                {
-                },
-            },
             ".calendarserver_version" :
             {
                 "@contents" : "2",
@@ -1115,12 +1072,6 @@
 
 
         after = {
-            "tasks" :
-            {
-                "incoming" :
-                {
-                },
-            },
             "calendars" :
             {
                 "__uids__" :

Modified: CalendarServer/branches/users/sagen/gm2submission/twistedcaldav/upgrade.py
===================================================================
--- CalendarServer/branches/users/sagen/gm2submission/twistedcaldav/upgrade.py	2011-04-29 \
                17:35:22 UTC (rev 7383)
+++ CalendarServer/branches/users/sagen/gm2submission/twistedcaldav/upgrade.py	2011-04-29 \
17:56:32 UTC (rev 7384) @@ -33,10 +33,14 @@
 from twistedcaldav.mail import MailGatewayTokensDatabase
 from twistedcaldav.ical import Component
 from twistedcaldav import caldavxml
+from twistedcaldav.ical import Component
+from twistedcaldav.scheduling.cuaddress import LocalCalendarUser
+from twistedcaldav.scheduling.scheduler import DirectScheduler
 
+
 from twisted.application.service import Service
 from twisted.internet import reactor
-from twisted.internet.defer import inlineCallbacks, succeed
+from twisted.internet.defer import inlineCallbacks, succeed, returnValue
 
 from calendarserver.tools.util import getDirectory
 from calendarserver.tools.resources import migrateResources
@@ -46,6 +50,8 @@
     "txdav.base.propertystore.xattr.PropertyStore.deadPropertyXattrPrefix"
 )
 
+INBOX_ITEMS = "inboxitems.txt"
+
 log = Logger()
 
 def xattrname(n):
@@ -318,22 +324,7 @@
             os.chown(journalPath, uid, gid)
 
 
-    def createTaskServiceDirectory(config, uid, gid):
 
-        taskDir = os.path.join(config.DataRoot, "tasks")
-        if not os.path.exists(taskDir):
-            os.mkdir(taskDir)
-        os.chown(taskDir, uid, gid)
-
-        incomingDir = os.path.join(taskDir, "incoming")
-        if not os.path.exists(incomingDir):
-            os.mkdir(incomingDir)
-        os.chown(incomingDir, uid, gid)
-
-        return incomingDir
-
-
-
     directory = getDirectory()
 
     docRoot = config.DocumentRoot
@@ -429,13 +420,12 @@
                                         if not inboxItem.startswith("."):
                                             inboxItems.add(os.path.join(inboxPath, \
inboxItem))  
-            incomingDir = createTaskServiceDirectory(config, uid, gid)
             if inboxItems:
-                taskFile = os.path.join(incomingDir, "scheduleinboxes.task")
-                with open(taskFile, "w") as out:
+                inboxItemsFile = os.path.join(config.DataRoot, INBOX_ITEMS)
+                with open(inboxItemsFile, "w") as out:
                     for item in inboxItems:
                         out.write("%s\n" % (item))
-                os.chown(taskFile, uid, gid)
+                os.chown(inboxItemsFile, uid, gid)
 
             if total:
                 log.warn("Processing %d calendar homes in %s" % (total, uidHomes))
@@ -713,3 +703,152 @@
 
 
 
+class PostDBImportService(Service, object):
+    """
+    Service for processing non-implicit inbox items after data has been
+    imported into the DB
+    """
+
+    def __init__(self, config, store, service):
+        """
+        Initialize the service.
+        """
+        self.wrappedService = service
+        self.store = store
+        self.config = config
+
+    def startService(self):
+        """
+        Start the service.
+        """
+        self.processInboxItems()
+
+
+    @inlineCallbacks
+    def processInboxItems(self):
+        """
+        When data is migrated from a non-implicit scheduling server there can
+        be inbox items that clients have not yet processed.  This method
+        runs those inbox items through the implicit scheduling mechanism.
+        """
+
+        inboxItemsList = os.path.join(self.config.DataRoot, INBOX_ITEMS)
+        if os.path.exists(inboxItemsList):
+
+            root = getRootResource(self.config, self.store)
+            directory = root.getDirectory()
+            principalCollection = directory.principalCollection
+
+            inboxItems = set()
+            with open(inboxItemsList) as input:
+                for inboxItem in input:
+                    inboxItem = inboxItem.strip()
+                    inboxItems.add(inboxItem)
+
+            try:
+                for inboxItem in list(inboxItems):
+                    log.info("Processing inbox item: %s" % (inboxItem,))
+                    ignore, uuid, ignore, fileName = inboxItem.rsplit("/", 3)
+
+                    record = directory.recordWithUID(uuid)
+                    if not record:
+                        continue
+
+                    principal = principalCollection.principalForRecord(record)
+                    if not principal:
+                        continue
+
+                    request = FakeRequest(root, "PUT", None)
+                    request.checkedSACL = True
+                    request.authnUser = request.authzUser = davxml.Principal(
+                        davxml.HRef.fromString("/principals/__uids__/%s/" % (uuid,))
+                    )
+
+                    calendarHome = yield principal.calendarHome(request)
+                    if not calendarHome:
+                        continue
+
+                    inbox = yield calendarHome.getChild("inbox")
+                    if inbox and inbox.exists():
+
+                        inboxItemResource = yield inbox.getChild(fileName)
+                        if inboxItemResource and inboxItemResource.exists():
+
+                            uri = "/calendars/__uids__/%s/inbox/%s" % (uuid,
+                                fileName)
+                            request.path = uri
+                            request._rememberResource(inboxItemResource, uri)
+
+                            yield self.processInboxItem(
+                                root,
+                                directory,
+                                principal,
+                                request,
+                                inbox,
+                                inboxItemResource,
+                                uuid,
+                                uri
+                            )
+                    inboxItems.remove(inboxItem)
+
+            except Exception, e:
+                log.error("Error processing inbox item: %s (%s)" % (inboxItem, e))
+                log.error("Restart calendar service to reattempt processing")
+
+            finally:
+                # Rewrite the inbox items file in case we exit before we're
+                # done so we'll pick up where we left off next time we start up.
+                if inboxItems:
+                    with open(inboxItemsList + ".tmp", "w") as output:
+                        for inboxItem in inboxItems:
+                            output.write("%s\n" % (inboxItem,))
+                    os.rename(inboxItemsList + ".tmp", inboxItemsList)
+                else:
+                    os.remove(inboxItemsList)
+
+        reactor.callLater(0, self.wrappedService.setServiceParent, self.parent)
+
+
+    @inlineCallbacks
+    def processInboxItem(self, root, directory, principal, request, inbox,
+        inboxItem, uuid, uri):
+        """
+        Run an individual inbox item through implicit scheduling and remove
+        the inbox item.
+        """
+
+        log.debug("Processing inbox item %s" % (inboxItem,))
+
+        ownerPrincipal = principal
+        cua = "urn:uuid:%s" % (uuid,)
+        owner = LocalCalendarUser(cua, ownerPrincipal,
+            inbox, ownerPrincipal.scheduleInboxURL())
+
+        data = yield inboxItem.iCalendarText()
+        calendar = Component.fromString(data)
+        try:
+            method = calendar.propertyValue("METHOD")
+        except ValueError:
+            returnValue(None)
+
+        if method == "REPLY":
+            # originator is attendee sending reply
+            originator = calendar.getAttendees()[0]
+        else:
+            # originator is the organizer
+            originator = calendar.getOrganizer()
+
+        principalCollection = directory.principalCollection
+        originatorPrincipal = \
principalCollection.principalForCalendarUserAddress(originator) +        originator = \
LocalCalendarUser(originator, originatorPrincipal) +        recipients = (owner,)
+
+        txn = request._newStoreTransaction
+        scheduler = DirectScheduler(request, inboxItem)
+        # Process inbox item
+        yield scheduler.doSchedulingViaPUT(originator, recipients, calendar,
+            internal_request=False)
+        # Remove item
+        yield inboxItem.storeRemove(request, True, uri)
+        yield txn.commit()
+


[Attachment #5 (text/html)]

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[7384] CalendarServer/branches/users/sagen/gm2submission</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: \
verdana,arial,helvetica,sans-serif; font-size: 10pt;  } #msg dl a { font-weight: \
bold} #msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: \
bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: \
6px; } #logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em \
0; } #logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg \
h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; } \
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; \
} #logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: \
-1.5em; padding-left: 1.5em; } #logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em \
1em 0 1em; background: white;} #logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid \
#fa0; border-bottom: 1px solid #fa0; background: #fff; } #logmsg table th { \
text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted \
#fa0; } #logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: \
0.2em 0.5em; } #logmsg table thead th { text-align: center; border-bottom: 1px solid \
#fa0; } #logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: \
6px; } #patch { width: 100%; }
#patch h4 {font-family: \
verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
 #patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, \
#patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins \
{background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del \
{background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, \
                .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a \
href="http://trac.macosforge.org/projects/calendarserver/changeset/7384">7384</a></dd>
 <dt>Author</dt> <dd>sagen@apple.com</dd>
<dt>Date</dt> <dd>2011-04-29 10:56:32 -0700 (Fri, 29 Apr 2011)</dd>
</dl>

<h3>Log Message</h3>
<pre>Applying inbox fix to branch</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesuserssagengm2submissioncalendarserversidecar__init \
__py">CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/__init__.py</a></li>
 <li><a href="#CalendarServerbranchesuserssagengm2submissioncalendarserversidecartaskp \
y">CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/task.py</a></li>
 <li><a href="#CalendarServerbranchesuserssagengm2submissioncalendarserversidecartest_ \
_init__py">CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/test/__init__.py</a></li>
 <li><a href="#CalendarServerbranchesuserssagengm2submissioncalendarserversidecartestt \
est_taskpy">CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/test/test_task.py</a></li>
 <li><a href="#CalendarServerbranchesuserssagengm2submissioncalendarservertapcaldavpy" \
>CalendarServer/branches/users/sagen/gm2submission/calendarserver/tap/caldav.py</a></li>
> 
<li><a href="#CalendarServerbranchesuserssagengm2submissiontwistedpluginscaldavpy">Cal \
endarServer/branches/users/sagen/gm2submission/twisted/plugins/caldav.py</a></li> \
<li><a href="#CalendarServerbranchesuserssagengm2submissiontwistedcaldavtesttest_upgra \
depy">CalendarServer/branches/users/sagen/gm2submission/twistedcaldav/test/test_upgrade.py</a></li>
 <li><a href="#CalendarServerbranchesuserssagengm2submissiontwistedcaldavupgradepy">Ca \
lendarServer/branches/users/sagen/gm2submission/twistedcaldav/upgrade.py</a></li> \
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServerbranchesuserssagengm2submissioncalendarserversidecar__init__py"></a>
 <div class="modfile"><h4>Modified: \
CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/__init__.py \
(7383 => 7384)</h4> <pre class="diff"><span>
<span class="info">--- \
CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/__init__.py	2011-04-29 \
                17:35:22 UTC (rev 7383)
+++ CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/__init__.py	2011-04-29 \
17:56:32 UTC (rev 7384) </span><span class="lines">@@ -1,19 +0,0 @@
</span><del>-##
-# Copyright (c) 2005-2009 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-&quot;&quot;&quot;
-CalendarServer &quot;sidecar&quot; processes
-&quot;&quot;&quot;
</del></span></pre></div>
<a id="CalendarServerbranchesuserssagengm2submissioncalendarserversidecartaskpy"></a>
<div class="modfile"><h4>Modified: \
CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/task.py \
(7383 => 7384)</h4> <pre class="diff"><span>
<span class="info">--- \
CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/task.py	2011-04-29 \
                17:35:22 UTC (rev 7383)
+++ CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/task.py	2011-04-29 \
17:56:32 UTC (rev 7384) </span><span class="lines">@@ -1,342 +0,0 @@
</span><del>-# Copyright (c) 2005-2010 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-from __future__ import with_statement
-
-__all__ = [
-    &quot;CalDAVTaskService&quot;,
-    &quot;CalDAVTaskServiceMaker&quot;,
-    &quot;CalDAVTaskOptions&quot;,
-    &quot;Task&quot;,
-]
-
-import os
-from datetime import date, timedelta
-
-from zope.interface import implements
-
-from twisted.application.service import MultiService, Service, IServiceMaker
-from twisted.internet.defer import DeferredList, inlineCallbacks, returnValue
-from twisted.internet.reactor import callLater
-from twisted.plugin import IPlugin
-from twisted.python.usage import Options, UsageError
-
-from twext.python.log import Logger, LoggingMixIn
-from twext.python.log import logLevelForNamespace, setLogLevelForNamespace
-
-from twistedcaldav.config import config
-from twistedcaldav.stdconfig import DEFAULT_CONFIG, DEFAULT_CONFIG_FILE
-from twistedcaldav.ical import Component
-from twistedcaldav.scheduling.cuaddress import LocalCalendarUser
-from twistedcaldav.scheduling.scheduler import DirectScheduler
-
-from calendarserver.tap.util import getRootResource, FakeRequest
-from calendarserver.tools.purge import purgeOldEvents
-
-log = Logger()
-
-@inlineCallbacks
-def processInboxItem(rootResource, directory, inboxFile, inboxItemFile, uuid):
-    log.debug(&quot;Processing inbox item %s&quot; % (inboxItemFile,))
-
-    principals = rootResource.getChild(&quot;principals&quot;)
-    ownerPrincipal = principals.principalForUID(uuid)
-    cua = &quot;urn:uuid:%s&quot; % (uuid,)
-    owner = LocalCalendarUser(cua, ownerPrincipal,
-        inboxFile, ownerPrincipal.scheduleInboxURL())
-
-    data = inboxItemFile.iCalendarText()
-    calendar = Component.fromString(data)
-    try:
-        method = calendar.propertyValue(&quot;METHOD&quot;)
-    except ValueError:
-        returnValue(None)
-
-    if method == &quot;REPLY&quot;:
-        # originator is attendee sending reply
-        originator = calendar.getAttendees()[0]
-    else:
-        # originator is the organizer
-        originator = calendar.getOrganizer()
-
-    originatorPrincipal = principals.principalForCalendarUserAddress(originator)
-    originator = LocalCalendarUser(originator, originatorPrincipal)
-    recipients = (owner,)
-    scheduler = DirectScheduler(FakeRequest(rootResource, &quot;PUT&quot;), \
                inboxItemFile)
-    yield scheduler.doSchedulingViaPUT(originator, recipients, calendar, \
                internal_request=False)
-
-    if os.path.exists(inboxItemFile.fp.path):
-        os.remove(inboxItemFile.fp.path)
-
-
-
-class Task(object):
-
-    def __init__(self, service, fileName):
-        self.service = service
-        self.taskName = fileName.split(&quot;.&quot;)[0]
-        self.taskFile = os.path.join(self.service.processingDir, fileName)
-
-    @inlineCallbacks
-    def run(self):
-        methodName = &quot;task_%s&quot; % (self.taskName,)
-        method = getattr(self, methodName, None)
-        if method:
-            try:
-                log.warn(&quot;Running task '%s'&quot; % (self.taskName))
-                yield method()
-                log.warn(&quot;Completed task '%s'&quot; % (self.taskName))
-            except Exception, e:
-                log.error(&quot;Failed task '%s' (%s)&quot; % (self.taskName, e))
-                os.remove(self.taskFile)
-                raise
-        else:
-            log.error(&quot;Unknown task requested: '%s'&quot; % (self.taskName))
-            os.remove(self.taskFile)
-            returnValue(None)
-
-    @inlineCallbacks
-    def task_scheduleinboxes(self):
-
-        calendars = self.service.root.getChild(&quot;calendars&quot;)
-        uidDir = calendars.getChild(&quot;__uids__&quot;)
-
-        inboxItems = set()
-        with open(self.taskFile) as input:
-            for inboxItem in input:
-                inboxItem = inboxItem.strip()
-                inboxItems.add(inboxItem)
-
-        for inboxItem in list(inboxItems):
-            log.info(&quot;Processing inbox item: %s&quot; % (inboxItem,))
-            ignore, uuid, ignore, fileName = inboxItem.rsplit(&quot;/&quot;, 3)
-
-            homeFile = uidDir.getChild(uuid)
-            if not homeFile:
-                continue
-
-            inboxFile = homeFile.getChild(&quot;inbox&quot;)
-            if not inboxFile:
-                continue
-
-            inboxItemFile = inboxFile.getChild(fileName)
-
-            yield processInboxItem(
-                self.service.root,
-                self.service.directory,
-                inboxFile,
-                inboxItemFile,
-                uuid
-            )
-            inboxItems.remove(inboxItem)
-
-            # Rewrite the task file in case we exit before we're done
-            with open(self.taskFile + &quot;.tmp&quot;, &quot;w&quot;) as output:
-                for inboxItem in inboxItems:
-                    output.write(&quot;%s\n&quot; % (inboxItem,))
-            os.rename(self.taskFile + &quot;.tmp&quot;, self.taskFile)
-
-        os.remove(self.taskFile)
-
-
-    @inlineCallbacks
-    def task_purgeoldevents(self):
-
-        with open(self.taskFile) as input:
-            try:
-                value = input.read().strip()
-                days = int(value)
-            except ValueError:
-                log.error(&quot;Illegal value for purge days: %s&quot; % (value,))
-            else:
-                cutoff = (date.today() -
-                    timedelta(days=days)).strftime(&quot;%Y%m%dT000000Z&quot;)
-                count = (yield purgeOldEvents(self.service.directory,
-                    self.service.root, cutoff))
-                log.info(&quot;Purged %d events&quot; % (count,))
-
-        os.remove(self.taskFile)
-
-
-class CalDAVTaskService(Service):
-
-    def __init__(self, root):
-        self.root = root
-        self.directory = root.directory
-        self.seconds = 30 # How often to check for new tasks in incomingDir
-        self.taskDir = os.path.join(config.DataRoot, &quot;tasks&quot;)
-        # New task files are placed into &quot;incoming&quot;
-        self.incomingDir = os.path.join(self.taskDir, &quot;incoming&quot;)
-        # Task files get moved into &quot;processing&quot; and then removed when \
                complete
-        self.processingDir = os.path.join(self.taskDir, &quot;processing&quot;)
-
-    def startService(self):
-        log.info(&quot;Starting task service&quot;)
-
-        if not os.path.exists(self.taskDir):
-            os.mkdir(self.taskDir)
-        if not os.path.exists(self.incomingDir):
-            os.mkdir(self.incomingDir)
-        if not os.path.exists(self.processingDir):
-            os.mkdir(self.processingDir)
-
-        callLater(self.seconds, self.periodic, first=True)
-
-
-    def periodic(self, first=False):
-        # log.debug(&quot;Checking for tasks&quot;)
-
-        deferreds = []
-
-        try:
-            if first:
-                # check the processing directory to see if there are any tasks
-                # that didn't complete during the last server run; start those
-                for fileName in os.listdir(self.processingDir):
-                    if fileName.endswith(&quot;.task&quot;):
-                        log.debug(&quot;Restarting old task: %s&quot; % (fileName,))
-                        deferreds.append(Task(self, fileName).run())
-
-            for fileName in os.listdir(self.incomingDir):
-                if fileName.endswith(&quot;.task&quot;):
-                    log.debug(&quot;Found new task: %s&quot; % (fileName,))
-                    os.rename(os.path.join(self.incomingDir, fileName),
-                        os.path.join(self.processingDir, fileName))
-                    deferreds.append(Task(self, fileName).run())
-
-        finally:
-            callLater(self.seconds, self.periodic)
-
-        return DeferredList(deferreds)
-
-
-
-class CalDAVTaskOptions(Options):
-    optParameters = [[
-        &quot;config&quot;, &quot;f&quot;, DEFAULT_CONFIG_FILE, &quot;Path to \
                configuration file.&quot;
-    ]]
-
-    def __init__(self, *args, **kwargs):
-        super(CalDAVTaskOptions, self).__init__(*args, **kwargs)
-
-        self.overrides = {}
-
-    def _coerceOption(self, configDict, key, value):
-        &quot;&quot;&quot;
-        Coerce the given C{val} to type of C{configDict[key]}
-        &quot;&quot;&quot;
-        if key in configDict:
-            if isinstance(configDict[key], bool):
-                value = value == &quot;True&quot;
-
-            elif isinstance(configDict[key], (int, float, long)):
-                value = type(configDict[key])(value)
-
-            elif isinstance(configDict[key], (list, tuple)):
-                value = value.split(',')
-
-            elif isinstance(configDict[key], dict):
-                raise UsageError(
-                    &quot;Dict options not supported on the command line&quot;
-                )
-
-            elif value == 'None':
-                value = None
-
-        return value
-
-    def _setOverride(self, configDict, path, value, overrideDict):
-        &quot;&quot;&quot;
-        Set the value at path in configDict
-        &quot;&quot;&quot;
-        key = path[0]
-
-        if len(path) == 1:
-            overrideDict[key] = self._coerceOption(configDict, key, value)
-            return
-
-        if key in configDict:
-            if not isinstance(configDict[key], dict):
-                raise UsageError(
-                    &quot;Found intermediate path element that is not a \
                dictionary&quot;
-                )
-
-            if key not in overrideDict:
-                overrideDict[key] = {}
-
-            self._setOverride(
-                configDict[key], path[1:],
-                value, overrideDict[key]
-            )
-
-
-    def opt_option(self, option):
-        &quot;&quot;&quot;
-        Set an option to override a value in the config file. True, False, int,
-        and float options are supported, as well as comma seperated lists. Only
-        one option may be given for each --option flag, however multiple
-        --option flags may be specified.
-        &quot;&quot;&quot;
-
-        if &quot;=&quot; in option:
-            path, value = option.split('=')
-            self._setOverride(
-                DEFAULT_CONFIG,
-                path.split('/'),
-                value,
-                self.overrides
-            )
-        else:
-            self.opt_option('%s=True' % (option,))
-
-    opt_o = opt_option
-
-    def postOptions(self):
-        config.load(self['config'])
-        config.updateDefaults(self.overrides)
-        self.parent['pidfile'] = None
-
-
-class CalDAVTaskServiceMaker (LoggingMixIn):
-    implements(IPlugin, IServiceMaker)
-
-    tapname = &quot;caldav_task&quot;
-    description = &quot;Calendar Server Task Process&quot;
-    options = CalDAVTaskOptions
-
-    def makeService(self, options):
-
-        svc = MultiService()
-        #
-        # The task sidecar doesn't care about system SACLs
-        #
-        config.EnableSACLs = False
-
-        #
-        # Change default log level to &quot;info&quot; as its useful to have
-        # that during startup
-        #
-        oldLogLevel = logLevelForNamespace(None)
-        setLogLevelForNamespace(None, &quot;info&quot;)
-
-        rootResource = getRootResource(config, svc)
-
-        CalDAVTaskService(rootResource).setServiceParent(svc)
-
-        # Change log level back to what it was before
-        setLogLevelForNamespace(None, oldLogLevel)
-
-        return svc
-
</del></span></pre></div>
<a id="CalendarServerbranchesuserssagengm2submissioncalendarserversidecartest__init__py"></a>
 <div class="modfile"><h4>Modified: \
CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/test/__init__.py \
(7383 => 7384)</h4> <pre class="diff"><span>
<span class="info">--- \
CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/test/__init__.py	2011-04-29 \
                17:35:22 UTC (rev 7383)
+++ CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/test/__init__.py	2011-04-29 \
17:56:32 UTC (rev 7384) </span><span class="lines">@@ -1,15 +0,0 @@
</span><del>-##
-# Copyright (c) 2010 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
</del></span></pre></div>
<a id="CalendarServerbranchesuserssagengm2submissioncalendarserversidecartesttest_taskpy"></a>
 <div class="modfile"><h4>Modified: \
CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/test/test_task.py \
(7383 => 7384)</h4> <pre class="diff"><span>
<span class="info">--- \
CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/test/test_task.py	2011-04-29 \
                17:35:22 UTC (rev 7383)
+++ CalendarServer/branches/users/sagen/gm2submission/calendarserver/sidecar/test/test_task.py	2011-04-29 \
17:56:32 UTC (rev 7384) </span><span class="lines">@@ -1,216 +0,0 @@
</span><del>-##
-# Copyright (c) 2009 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-import os, zlib
-
-from calendarserver.sidecar.task import CalDAVTaskServiceMaker, CalDAVTaskOptions, \
                Task
-from os.path import dirname, abspath
-from twext.python.plistlib import writePlist
-from twisted.python.usage import Options
-from twistedcaldav.config import config, ConfigDict
-from twistedcaldav.stdconfig import DEFAULT_CONFIG
-from twistedcaldav.test.util import TestCase, todo
-from twisted.internet.defer import inlineCallbacks
-
-# Points to top of source tree.
-sourceRoot = dirname(dirname(dirname(dirname(abspath(__file__)))))
-
-
-# TODO: update or delete task sidecar
-class CalDAVTaskServiceTest(object): # TestCase):
-    &quot;&quot;&quot;
-    Test various parameters of our usage.Options subclass
-    &quot;&quot;&quot;
-    def setUp(self):
-        &quot;&quot;&quot;
-        Set up our options object, giving it a parent, and forcing the
-        global config to be loaded from defaults.
-        &quot;&quot;&quot;
-        TestCase.setUp(self)
-        self.options = CalDAVTaskOptions()
-        self.options.parent = Options()
-        self.options.parent[&quot;uid&quot;] = 0
-        self.options.parent[&quot;gid&quot;] = 0
-        self.options.parent[&quot;nodaemon&quot;] = False
-
-        self.config = ConfigDict(DEFAULT_CONFIG)
-
-        accountsFile = os.path.join(sourceRoot, \
                &quot;twistedcaldav/directory/test/accounts.xml&quot;)
-        self.config[&quot;DirectoryService&quot;] = {
-            &quot;params&quot;: {&quot;xmlFile&quot;: accountsFile},
-            &quot;type&quot;: \
                &quot;twistedcaldav.directory.xmlfile.XMLDirectoryService&quot;
-        }
-
-        self.config.DocumentRoot   = self.mktemp()
-        self.config.DataRoot       = self.mktemp()
-        self.config.ProcessType    = &quot;Single&quot;
-        self.config.Memcached.ClientEnabled = False
-        self.config.Memcached.ServerEnabled = False
-
-
-        pemFile = os.path.join(sourceRoot, \
                &quot;twistedcaldav/test/data/server.pem&quot;)
-        self.config.SSLPrivateKey = pemFile
-        self.config.SSLCertificate = pemFile
-
-        os.mkdir(self.config.DocumentRoot)
-        os.mkdir(self.config.DataRoot)
-
-        self.configFile = self.mktemp()
-
-        self.writeConfig()
-
-    def writeConfig(self):
-        &quot;&quot;&quot;
-        Flush self.config out to self.configFile
-        &quot;&quot;&quot;
-        writePlist(self.config, self.configFile)
-
-    def tearDown(self):
-        config.setDefaults(DEFAULT_CONFIG)
-        config.reload()
-
-    def makeService(self):
-        self.options.parseOptions([&quot;-f&quot;, self.configFile])
-        return CalDAVTaskServiceMaker().makeService(self.options)
-
-    @todo(&quot;FIXME: fix after new store changes&quot;)
-    @inlineCallbacks
-    def test_taskService(self):
-        service = self.makeService()
-
-        structure = {
-            &quot;calendars&quot; : {
-                &quot;__uids__&quot; : {
-                    &quot;64&quot; : {
-                        &quot;23&quot; : {
-                            &quot;6423F94A-6B76-4A3A-815B-D52CFD77935D&quot; : {
-                                &quot;calendar&quot;: {
-                                    &quot;@xattrs&quot; :
-                                    {
-                                        &quot;WebDAV:{DAV:}resourcetype&quot; : \
zlib.compress(&quot;&lt;?xml version='1.0' encoding='UTF-8'?&gt;\r\n&lt;resourcetype \
xmlns='DAV:'&gt;\r\n&lt;collection/&gt;\r\n&lt;calendar \
                xmlns='urn:ietf:params:xml:ns:caldav'/&gt;\r\n&lt;/resourcetype&gt;\r\n&quot;),
                
-                                    },
-                                },
-                                &quot;inbox&quot;: {
-                                    &quot;unprocessed.ics&quot;: {
-                                        &quot;@contents&quot; : unprocessed,
-                                    }
-                                },
-                            }
-                        }
-                    }
-                }
-            },
-        }
-
-        self.createHierarchy(structure, root=self.config.DocumentRoot)
-
-        structure = {
-            &quot;tasks&quot; : {
-                &quot;incoming&quot; : { },
-                &quot;processing&quot; : {
-                    &quot;scheduleinboxes.task&quot; : {
-                        &quot;@contents&quot; : os.path.join(
-                            self.config.DocumentRoot,
-                            &quot;calendars&quot;,
-                            &quot;__uids__&quot;,
-                            &quot;64&quot;,
-                            &quot;23&quot;,
-                            &quot;6423F94A-6B76-4A3A-815B-D52CFD77935D&quot;,
-                            &quot;inbox&quot;,
-                            &quot;unprocessed.ics&quot;
-                        ),
-                    },
-                },
-            },
-        }
-
-        self.createHierarchy(structure, root=self.config.DataRoot)
-
-        task = Task(service, &quot;scheduleinboxes.task&quot;)
-        yield task.run()
-
-        # Aftwards we want to see a .ics file in calendar and inbox
-        structure = {
-            &quot;calendars&quot; : {
-                &quot;__uids__&quot; : {
-                    &quot;64&quot; : {
-                        &quot;23&quot; : {
-                            &quot;6423F94A-6B76-4A3A-815B-D52CFD77935D&quot; : {
-                                &quot;calendar&quot;: {
-                                    &quot;.db.sqlite&quot; : {
-                                        &quot;@contents&quot; : None,
-                                    },
-                                    &quot;*.ics&quot;: {
-                                        &quot;@contents&quot; : None,
-                                    },
-                                },
-                                &quot;inbox&quot;: {
-                                    &quot;.db.sqlite&quot; : {
-                                        &quot;@contents&quot; : None,
-                                    },
-                                    &quot;*.ics&quot;: {
-                                        &quot;@contents&quot; : None,
-                                    },
-                                },
-                            }
-                        }
-                    }
-                }
-            },
-        }
-        self.assertTrue(self.verifyHierarchy(self.config.DocumentRoot, structure))
-
-unprocessed = &quot;&quot;&quot;BEGIN:VCALENDAR
-VERSION:2.0
-CALSCALE:GREGORIAN
-METHOD:REQUEST
-PRODID:-//Apple Inc.//iCal 4.0.1//EN
-BEGIN:VTIMEZONE
-TZID:US/Pacific
-BEGIN:STANDARD
-DTSTART:20071104T020000
-RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
-TZNAME:PST
-TZOFFSETFROM:-0700
-TZOFFSETTO:-0800
-END:STANDARD
-BEGIN:DAYLIGHT
-DTSTART:20070311T020000
-RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
-TZNAME:PDT
-TZOFFSETFROM:-0800
-TZOFFSETTO:-0700
-END:DAYLIGHT
-END:VTIMEZONE
-BEGIN:VEVENT
-UID:A40F4892-B40F-4C0F-B8D0-F4EB2C97F4B9
-DTSTART;TZID=US/Pacific:20091209T120000
-DTEND;TZID=US/Pacific:20091209T130000
-ATTENDEE;CN=Wilfredo Sanchez;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=N
- EEDS-ACTION;EMAIL=wsanchez@example.com;RSVP=TRUE:/principals/__uids__/6423F94
- A-6B76-4A3A-815B-D52CFD77935D/
-ATTENDEE;CUTYPE=INDIVIDUAL;CN=Morgen Sagen;PARTSTAT=ACCEPTED:mailto:sagen@exam
- ple.com
-CREATED:20091209T183541Z
-DTSTAMP:20091209T183612Z
-ORGANIZER;CN=Morgen Sagen:mailto:sagen@example.com
-SEQUENCE:6
-SUMMARY:Test
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR
-&quot;&quot;&quot;.replace(&quot;\n&quot;, &quot;\r\n&quot;)
-
</del></span></pre></div>
<a id="CalendarServerbranchesuserssagengm2submissioncalendarservertapcaldavpy"></a>
<div class="modfile"><h4>Modified: \
CalendarServer/branches/users/sagen/gm2submission/calendarserver/tap/caldav.py (7383 \
=> 7384)</h4> <pre class="diff"><span>
<span class="info">--- \
CalendarServer/branches/users/sagen/gm2submission/calendarserver/tap/caldav.py	2011-04-29 \
                17:35:22 UTC (rev 7383)
+++ CalendarServer/branches/users/sagen/gm2submission/calendarserver/tap/caldav.py	2011-04-29 \
17:56:32 UTC (rev 7384) </span><span class="lines">@@ -69,7 +69,7 @@
</span><span class="cx"> from twistedcaldav.mail import IMIPReplyInboxResource
</span><span class="cx"> from twistedcaldav import memcachepool
</span><span class="cx"> from twistedcaldav.stdconfig import DEFAULT_CONFIG, \
DEFAULT_CONFIG_FILE </span><del>-from twistedcaldav.upgrade import \
UpgradeFileSystemFormatService </del><ins>+from twistedcaldav.upgrade import \
UpgradeFileSystemFormatService, PostDBImportService </ins><span class="cx"> 
</span><span class="cx"> from calendarserver.tap.util import pgServiceFromConfig
</span><span class="cx"> 
</span><span class="lines">@@ -429,7 +429,6 @@
</span><span class="cx">     L{DelayedStartupProcessMonitor}:
</span><span class="cx"> 
</span><span class="cx">         - regular slave processes (CalDAV workers)
</span><del>-        - task sidecar
</del><span class="cx">         - notifier
</span><span class="cx">         - mail gateway
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -506,27 +505,8 @@
</span><span class="cx">             self.monitor.addProcess(&quot;mailgateway&quot;, \
mailGatewayArgv, </span><span class="cx">                                \
env=PARENT_ENVIRONMENT) </span><span class="cx"> 
</span><del>-        self.maker.log_info(&quot;Adding task service&quot;)
-        taskArgv = [
-            sys.executable,
-            sys.argv[0],
-        ]
-        if config.UserName:
-            taskArgv.extend((&quot;-u&quot;, config.UserName))
-        if config.GroupName:
-            taskArgv.extend((&quot;-g&quot;, config.GroupName))
-        taskArgv.extend((
-            &quot;--reactor=%s&quot; % (config.Twisted.reactor,),
-            &quot;-n&quot;, &quot;caldav_task&quot;,
-            &quot;-f&quot;, self.configPath,
-        ))
</del><span class="cx"> 
</span><del>-        self.monitor.addProcess(
-            &quot;caldav_task&quot;, taskArgv, env=PARENT_ENVIRONMENT
-        )
</del><span class="cx"> 
</span><del>-
-
</del><span class="cx"> class CalDAVServiceMaker (LoggingMixIn):
</span><span class="cx">     implements(IPlugin, IServiceMaker)
</span><span class="cx"> 
</span><span class="lines">@@ -982,7 +962,8 @@
</span><span class="cx">             mainService = createMainService(cp, store)
</span><span class="cx">             upgradeSvc = \
UpgradeFileSystemFormatService(config, </span><span class="cx">                 \
UpgradeToDatabaseService.wrapService( </span><del>-                    \
CachingFilePath(config.DocumentRoot), mainService, </del><ins>+                    \
CachingFilePath(config.DocumentRoot), +                    \
PostDBImportService(config, store, mainService), </ins><span class="cx">              \
store, uid=uid, gid=gid </span><span class="cx">                 )
</span><span class="cx">             )
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagengm2submissiontwistedpluginscaldavpy"></a>
<div class="modfile"><h4>Modified: \
CalendarServer/branches/users/sagen/gm2submission/twisted/plugins/caldav.py (7383 => \
7384)</h4> <pre class="diff"><span>
<span class="info">--- \
CalendarServer/branches/users/sagen/gm2submission/twisted/plugins/caldav.py	2011-04-29 \
                17:35:22 UTC (rev 7383)
+++ CalendarServer/branches/users/sagen/gm2submission/twisted/plugins/caldav.py	2011-04-29 \
17:56:32 UTC (rev 7384) </span><span class="lines">@@ -50,6 +50,5 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> TwistedCalDAV     = \
TAP(&quot;calendarserver.tap.caldav.CalDAVServiceMaker&quot;) </span><del>-CalDAVTask \
= TAP(&quot;calendarserver.sidecar.task.CalDAVTaskServiceMaker&quot;) </del><span \
class="cx"> CalDAVNotifier    = \
TAP(&quot;twistedcaldav.notify.NotificationServiceMaker&quot;) </span><span \
class="cx"> CalDAVMailGateway = \
TAP(&quot;twistedcaldav.mail.MailGatewayServiceMaker&quot;) \
</span></span></pre></div> <a \
id="CalendarServerbranchesuserssagengm2submissiontwistedcaldavtesttest_upgradepy"></a>
 <div class="modfile"><h4>Modified: \
CalendarServer/branches/users/sagen/gm2submission/twistedcaldav/test/test_upgrade.py \
(7383 => 7384)</h4> <pre class="diff"><span>
<span class="info">--- \
CalendarServer/branches/users/sagen/gm2submission/twistedcaldav/test/test_upgrade.py	2011-04-29 \
                17:35:22 UTC (rev 7383)
+++ CalendarServer/branches/users/sagen/gm2submission/twistedcaldav/test/test_upgrade.py	2011-04-29 \
17:56:32 UTC (rev 7384) </span><span class="lines">@@ -318,7 +318,6 @@
</span><span class="cx">             },
</span><span class="cx">             MailGatewayTokensDatabase.dbFilename : { \
&quot;@contents&quot; : None }, </span><span class="cx">             \
&quot;%s-journal&quot; % (MailGatewayTokensDatabase.dbFilename,) : { \
&quot;@contents&quot; : None }, </span><del>-            &quot;tasks&quot; : \
{&quot;incoming&quot; : {}} </del><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         (yield self.verifyDirectoryComparison(before, \
after)) </span><span class="lines">@@ -385,12 +384,6 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         after = {
</span><del>-            &quot;tasks&quot; :
-            {
-                &quot;incoming&quot; :
-                {
-                },
-            },
</del><span class="cx">             &quot;.calendarserver_version&quot; :
</span><span class="cx">             {
</span><span class="cx">                 &quot;@contents&quot; : &quot;2&quot;,
</span><span class="lines">@@ -505,12 +498,6 @@
</span><span class="cx">                 {
</span><span class="cx">                 },
</span><span class="cx">             },
</span><del>-            &quot;tasks&quot; :
-            {
-                &quot;incoming&quot; :
-                {
-                },
-            },
</del><span class="cx">             &quot;.calendarserver_version&quot; :
</span><span class="cx">             {
</span><span class="cx">                 &quot;@contents&quot; : &quot;2&quot;,
</span><span class="lines">@@ -597,12 +584,6 @@
</span><span class="cx">                 {
</span><span class="cx">                 },
</span><span class="cx">             },
</span><del>-            &quot;tasks&quot; :
-            {
-                &quot;incoming&quot; :
-                {
-                },
-            },
</del><span class="cx">             &quot;.calendarserver_version&quot; :
</span><span class="cx">             {
</span><span class="cx">                 &quot;@contents&quot; : &quot;2&quot;,
</span><span class="lines">@@ -691,12 +672,6 @@
</span><span class="cx">             {
</span><span class="cx">                 &quot;@contents&quot; : &quot;&quot;,
</span><span class="cx">             },
</span><del>-            &quot;tasks&quot; :
-            {
-                &quot;incoming&quot; :
-                {
-                },
-            },
</del><span class="cx">             &quot;.calendarserver_version&quot; :
</span><span class="cx">             {
</span><span class="cx">                 &quot;@contents&quot; : &quot;2&quot;,
</span><span class="lines">@@ -770,12 +745,6 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         after = {
</span><del>-            &quot;tasks&quot; :
-            {
-                &quot;incoming&quot; :
-                {
-                },
-            },
</del><span class="cx">             &quot;.calendarserver_version&quot; :
</span><span class="cx">             {
</span><span class="cx">                 &quot;@contents&quot; : &quot;2&quot;,
</span><span class="lines">@@ -886,12 +855,6 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         after = {
</span><del>-            &quot;tasks&quot; :
-            {
-                &quot;incoming&quot; :
-                {
-                },
-            },
</del><span class="cx">             &quot;.calendarserver_version&quot; :
</span><span class="cx">             {
</span><span class="cx">                 &quot;@contents&quot; : &quot;2&quot;,
</span><span class="lines">@@ -1006,12 +969,6 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         after = {
</span><del>-            &quot;tasks&quot; :
-            {
-                &quot;incoming&quot; :
-                {
-                },
-            },
</del><span class="cx">             &quot;.calendarserver_version&quot; :
</span><span class="cx">             {
</span><span class="cx">                 &quot;@contents&quot; : &quot;2&quot;,
</span><span class="lines">@@ -1115,12 +1072,6 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">         after = {
</span><del>-            &quot;tasks&quot; :
-            {
-                &quot;incoming&quot; :
-                {
-                },
-            },
</del><span class="cx">             &quot;calendars&quot; :
</span><span class="cx">             {
</span><span class="cx">                 &quot;__uids__&quot; :
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagengm2submissiontwistedcaldavupgradepy"></a>
<div class="modfile"><h4>Modified: \
CalendarServer/branches/users/sagen/gm2submission/twistedcaldav/upgrade.py (7383 => \
7384)</h4> <pre class="diff"><span>
<span class="info">--- \
CalendarServer/branches/users/sagen/gm2submission/twistedcaldav/upgrade.py	2011-04-29 \
                17:35:22 UTC (rev 7383)
+++ CalendarServer/branches/users/sagen/gm2submission/twistedcaldav/upgrade.py	2011-04-29 \
17:56:32 UTC (rev 7384) </span><span class="lines">@@ -33,10 +33,14 @@
</span><span class="cx"> from twistedcaldav.mail import MailGatewayTokensDatabase
</span><span class="cx"> from twistedcaldav.ical import Component
</span><span class="cx"> from twistedcaldav import caldavxml
</span><ins>+from twistedcaldav.ical import Component
+from twistedcaldav.scheduling.cuaddress import LocalCalendarUser
+from twistedcaldav.scheduling.scheduler import DirectScheduler
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx"> from twisted.application.service import Service
</span><span class="cx"> from twisted.internet import reactor
</span><del>-from twisted.internet.defer import inlineCallbacks, succeed
</del><ins>+from twisted.internet.defer import inlineCallbacks, succeed, returnValue
</ins><span class="cx"> 
</span><span class="cx"> from calendarserver.tools.util import getDirectory
</span><span class="cx"> from calendarserver.tools.resources import migrateResources
</span><span class="lines">@@ -46,6 +50,8 @@
</span><span class="cx">     \
&quot;txdav.base.propertystore.xattr.PropertyStore.deadPropertyXattrPrefix&quot; \
</span><span class="cx"> ) </span><span class="cx"> 
</span><ins>+INBOX_ITEMS = &quot;inboxitems.txt&quot;
+
</ins><span class="cx"> log = Logger()
</span><span class="cx"> 
</span><span class="cx"> def xattrname(n):
</span><span class="lines">@@ -318,22 +324,7 @@
</span><span class="cx">             os.chown(journalPath, uid, gid)
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-    def createTaskServiceDirectory(config, uid, gid):
</del><span class="cx"> 
</span><del>-        taskDir = os.path.join(config.DataRoot, &quot;tasks&quot;)
-        if not os.path.exists(taskDir):
-            os.mkdir(taskDir)
-        os.chown(taskDir, uid, gid)
-
-        incomingDir = os.path.join(taskDir, &quot;incoming&quot;)
-        if not os.path.exists(incomingDir):
-            os.mkdir(incomingDir)
-        os.chown(incomingDir, uid, gid)
-
-        return incomingDir
-
-
-
</del><span class="cx">     directory = getDirectory()
</span><span class="cx"> 
</span><span class="cx">     docRoot = config.DocumentRoot
</span><span class="lines">@@ -429,13 +420,12 @@
</span><span class="cx">                                         if not \
inboxItem.startswith(&quot;.&quot;): </span><span class="cx">                         \
inboxItems.add(os.path.join(inboxPath, inboxItem)) </span><span class="cx"> 
</span><del>-            incomingDir = createTaskServiceDirectory(config, uid, gid)
</del><span class="cx">             if inboxItems:
</span><del>-                taskFile = os.path.join(incomingDir, \
                &quot;scheduleinboxes.task&quot;)
-                with open(taskFile, &quot;w&quot;) as out:
</del><ins>+                inboxItemsFile = os.path.join(config.DataRoot, \
INBOX_ITEMS) +                with open(inboxItemsFile, &quot;w&quot;) as out:
</ins><span class="cx">                     for item in inboxItems:
</span><span class="cx">                         out.write(&quot;%s\n&quot; % (item))
</span><del>-                os.chown(taskFile, uid, gid)
</del><ins>+                os.chown(inboxItemsFile, uid, gid)
</ins><span class="cx"> 
</span><span class="cx">             if total:
</span><span class="cx">                 log.warn(&quot;Processing %d calendar homes \
in %s&quot; % (total, uidHomes)) </span><span class="lines">@@ -713,3 +703,152 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+class PostDBImportService(Service, object):
+    &quot;&quot;&quot;
+    Service for processing non-implicit inbox items after data has been
+    imported into the DB
+    &quot;&quot;&quot;
+
+    def __init__(self, config, store, service):
+        &quot;&quot;&quot;
+        Initialize the service.
+        &quot;&quot;&quot;
+        self.wrappedService = service
+        self.store = store
+        self.config = config
+
+    def startService(self):
+        &quot;&quot;&quot;
+        Start the service.
+        &quot;&quot;&quot;
+        self.processInboxItems()
+
+
+    @inlineCallbacks
+    def processInboxItems(self):
+        &quot;&quot;&quot;
+        When data is migrated from a non-implicit scheduling server there can
+        be inbox items that clients have not yet processed.  This method
+        runs those inbox items through the implicit scheduling mechanism.
+        &quot;&quot;&quot;
+
+        inboxItemsList = os.path.join(self.config.DataRoot, INBOX_ITEMS)
+        if os.path.exists(inboxItemsList):
+
+            root = getRootResource(self.config, self.store)
+            directory = root.getDirectory()
+            principalCollection = directory.principalCollection
+
+            inboxItems = set()
+            with open(inboxItemsList) as input:
+                for inboxItem in input:
+                    inboxItem = inboxItem.strip()
+                    inboxItems.add(inboxItem)
+
+            try:
+                for inboxItem in list(inboxItems):
+                    log.info(&quot;Processing inbox item: %s&quot; % (inboxItem,))
+                    ignore, uuid, ignore, fileName = inboxItem.rsplit(&quot;/&quot;, \
3) +
+                    record = directory.recordWithUID(uuid)
+                    if not record:
+                        continue
+
+                    principal = principalCollection.principalForRecord(record)
+                    if not principal:
+                        continue
+
+                    request = FakeRequest(root, &quot;PUT&quot;, None)
+                    request.checkedSACL = True
+                    request.authnUser = request.authzUser = davxml.Principal(
+                        davxml.HRef.fromString(&quot;/principals/__uids__/%s/&quot; \
% (uuid,)) +                    )
+
+                    calendarHome = yield principal.calendarHome(request)
+                    if not calendarHome:
+                        continue
+
+                    inbox = yield calendarHome.getChild(&quot;inbox&quot;)
+                    if inbox and inbox.exists():
+
+                        inboxItemResource = yield inbox.getChild(fileName)
+                        if inboxItemResource and inboxItemResource.exists():
+
+                            uri = &quot;/calendars/__uids__/%s/inbox/%s&quot; % \
(uuid, +                                fileName)
+                            request.path = uri
+                            request._rememberResource(inboxItemResource, uri)
+
+                            yield self.processInboxItem(
+                                root,
+                                directory,
+                                principal,
+                                request,
+                                inbox,
+                                inboxItemResource,
+                                uuid,
+                                uri
+                            )
+                    inboxItems.remove(inboxItem)
+
+            except Exception, e:
+                log.error(&quot;Error processing inbox item: %s (%s)&quot; % \
(inboxItem, e)) +                log.error(&quot;Restart calendar service to \
reattempt processing&quot;) +
+            finally:
+                # Rewrite the inbox items file in case we exit before we're
+                # done so we'll pick up where we left off next time we start up.
+                if inboxItems:
+                    with open(inboxItemsList + &quot;.tmp&quot;, &quot;w&quot;) as \
output: +                        for inboxItem in inboxItems:
+                            output.write(&quot;%s\n&quot; % (inboxItem,))
+                    os.rename(inboxItemsList + &quot;.tmp&quot;, inboxItemsList)
+                else:
+                    os.remove(inboxItemsList)
+
+        reactor.callLater(0, self.wrappedService.setServiceParent, self.parent)
+
+
+    @inlineCallbacks
+    def processInboxItem(self, root, directory, principal, request, inbox,
+        inboxItem, uuid, uri):
+        &quot;&quot;&quot;
+        Run an individual inbox item through implicit scheduling and remove
+        the inbox item.
+        &quot;&quot;&quot;
+
+        log.debug(&quot;Processing inbox item %s&quot; % (inboxItem,))
+
+        ownerPrincipal = principal
+        cua = &quot;urn:uuid:%s&quot; % (uuid,)
+        owner = LocalCalendarUser(cua, ownerPrincipal,
+            inbox, ownerPrincipal.scheduleInboxURL())
+
+        data = yield inboxItem.iCalendarText()
+        calendar = Component.fromString(data)
+        try:
+            method = calendar.propertyValue(&quot;METHOD&quot;)
+        except ValueError:
+            returnValue(None)
+
+        if method == &quot;REPLY&quot;:
+            # originator is attendee sending reply
+            originator = calendar.getAttendees()[0]
+        else:
+            # originator is the organizer
+            originator = calendar.getOrganizer()
+
+        principalCollection = directory.principalCollection
+        originatorPrincipal = \
principalCollection.principalForCalendarUserAddress(originator) +        originator = \
LocalCalendarUser(originator, originatorPrincipal) +        recipients = (owner,)
+
+        txn = request._newStoreTransaction
+        scheduler = DirectScheduler(request, inboxItem)
+        # Process inbox item
+        yield scheduler.doSchedulingViaPUT(originator, recipients, calendar,
+            internal_request=False)
+        # Remove item
+        yield inboxItem.storeRemove(request, True, uri)
+        yield txn.commit()
+
</ins></span></pre>
</div>
</div>

</body>
</html>



_______________________________________________
calendarserver-changes mailing list
calendarserver-changes@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/calendarserver-changes


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic