[CalendarServer-changes] [15473] CalendarServer/trunk/calendarserver/tools/calverify.py

source_changes at macosforge.org source_changes at macosforge.org
Fri Mar 11 19:52:28 PST 2016


Revision: 15473
          http://trac.calendarserver.org//changeset/15473
Author:   cdaboo at apple.com
Date:     2016-03-11 19:52:28 -0800 (Fri, 11 Mar 2016)
Log Message:
-----------
Add option to upgrade calendar data by scanning/reading each resource.

Modified Paths:
--------------
    CalendarServer/trunk/calendarserver/tools/calverify.py

Modified: CalendarServer/trunk/calendarserver/tools/calverify.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/calverify.py	2016-03-12 00:49:48 UTC (rev 15472)
+++ CalendarServer/trunk/calendarserver/tools/calverify.py	2016-03-12 03:52:28 UTC (rev 15473)
@@ -239,6 +239,7 @@
 --double            : detect double-bookings.
 --dark-purge        : purge room/resource events with invalid organizer
 --split             : split recurring event
+--upgrade           : upgrade iCalendar data.
 
 --nuke PATH|RID     : remove specific calendar resources - can
                       only be used by itself. PATH is the full
@@ -251,7 +252,7 @@
 --config   : caldavd.plist file for the server.
 -v         : verbose logging
 
-Options for --ical:
+Options for --ical / --upgrade:
 
 --uuid     : only scan specified calendar homes. Can be a partial GUID
              to scan all GUIDs with that as a prefix.
@@ -336,6 +337,8 @@
         ['dark-purge', 'p', "Purge room/resource events with invalid organizer."],
         ['missing-location', 'g', "Room events with missing location."],
         ['split', 'l', "Split an event."],
+        ['upgrade', 'u', "Upgrade calendar data."],
+
         ['fix', 'x', "Fix problems."],
         ['verbose', 'v', "Verbose logging."],
         ['details', 'V', "Detailed logging."],
@@ -2994,6 +2997,153 @@
 
 
 
+class UpgradeDataService(CalVerifyService):
+    """
+    Service which scans calendar data.
+    """
+
+    def title(self):
+        return "Upgrade Data Service"
+
+
+    @inlineCallbacks
+    def doAction(self):
+
+        self.output.write("\n---- Scanning calendar data ----\n")
+
+        self.now = DateTime.getNowUTC()
+        self.start = DateTime.getToday()
+        self.start.setDateOnly(False)
+        self.end = self.start.duplicate()
+        self.end.offsetYear(1)
+        self.fix = self.options["fix"]
+
+        self.tzid = Timezone(tzid=self.options["tzid"] if self.options["tzid"] else "America/Los_Angeles")
+
+        self.txn = self.store.newTransaction()
+
+        if self.options["verbose"]:
+            t = time.time()
+        descriptor = None
+        if self.options["uuid"]:
+            rows = yield self.getAllResourceInfoWithUUID(self.options["uuid"], inbox=True)
+            descriptor = "getAllResourceInfoWithUUID"
+        elif self.options["uid"]:
+            rows = yield self.getAllResourceInfoWithUID(self.options["uid"], inbox=True)
+            descriptor = "getAllResourceInfoWithUID"
+        else:
+            rows = yield self.getAllResourceInfo(inbox=True)
+            descriptor = "getAllResourceInfo"
+
+        yield self.txn.commit()
+        self.txn = None
+
+        if self.options["verbose"]:
+            self.output.write("%s time: %.1fs\n" % (descriptor, time.time() - t,))
+
+        self.total = len(rows)
+        self.logResult("Number of events to process", self.total)
+        self.addSummaryBreak()
+
+        yield self.calendarDataUpgrade(rows)
+
+        self.printSummary()
+
+
+    @inlineCallbacks
+    def calendarDataUpgrade(self, rows):
+        """
+        Check each calendar resource for valid iCalendar data.
+        """
+
+        self.output.write("\n---- Upgrading each calendar object resource ----\n")
+        self.txn = self.store.newTransaction()
+
+        if self.options["verbose"]:
+            t = time.time()
+
+        results_bad = []
+        count = 0
+        total = len(rows)
+        upgradelen = 0
+        badlen = 0
+        rjust = 10
+        for owner, resid, uid, _ignore_calname, _ignore_md5, _ignore_organizer, _ignore_created, _ignore_modified in rows:
+            try:
+                calendarObj = yield CalendarStoreFeatures(self.txn._store).calendarObjectWithID(self.txn, resid)
+                if calendarObj._dataversion < calendarObj._currentDataVersion:
+                    upgradelen += 1
+                yield calendarObj.component(doUpdate=True)
+                result = True
+            except Exception, e:
+                result = False
+                message = "Exception when reading resource"
+                if self.options["verbose"]:
+                    print(e)
+            if not result:
+                results_bad.append((owner, uid, resid, message))
+                badlen += 1
+            count += 1
+            if self.options["verbose"]:
+                if count == 1:
+                    self.output.write("Upgraded".rjust(rjust) + "Bad".rjust(rjust) + "Current".rjust(rjust) + "Total".rjust(rjust) + "Complete".rjust(rjust) + "\n")
+                if divmod(count, 100)[1] == 0:
+                    self.output.write((
+                        "\r" +
+                        ("%s" % upgradelen).rjust(rjust) +
+                        ("%s" % badlen).rjust(rjust) +
+                        ("%s" % count).rjust(rjust) +
+                        ("%s" % total).rjust(rjust) +
+                        ("%d%%" % safePercent(count, total)).rjust(rjust)
+                    ).ljust(80))
+                    self.output.flush()
+
+            # To avoid holding locks on all the rows scanned, commit every 100 resources
+            if divmod(count, 100)[1] == 0:
+                yield self.txn.commit()
+                self.txn = self.store.newTransaction()
+
+        yield self.txn.commit()
+        self.txn = None
+        if self.options["verbose"]:
+            self.output.write((
+                "\r" +
+                ("%s" % upgradelen).rjust(rjust) +
+                ("%s" % badlen).rjust(rjust) +
+                ("%s" % count).rjust(rjust) +
+                ("%s" % total).rjust(rjust) +
+                ("%d%%" % safePercent(count, total)).rjust(rjust)
+            ).ljust(80) + "\n")
+
+        # Print table of results
+        table = tables.Table()
+        table.addHeader(("Owner", "Event UID", "RID", "Problem",))
+        for item in sorted(results_bad, key=lambda x: (x[0], x[1])):
+            owner, uid, resid, message = item
+            owner_record = yield self.directoryService().recordWithUID(owner)
+            table.addRow((
+                "%s/%s (%s)" % (owner_record.recordType if owner_record else "-", owner_record.shortNames[0] if owner_record else "-", owner,),
+                uid,
+                resid,
+                message,
+            ))
+
+        self.output.write("\n")
+        self.logResult("Upgraded iCalendar data", upgradelen, total)
+        self.logResult("Bad iCalendar data", len(results_bad), total)
+        self.results["Upgraded iCalendar data"] = upgradelen
+        self.results["Bad iCalendar data"] = results_bad
+        table.printTable(os=self.output)
+
+        if self.options["verbose"]:
+            diff_time = time.time() - t
+            self.output.write("Time: %.2f s  Average: %.1f ms/resource\n" % (
+                diff_time,
+                safePercent(diff_time, total, 1000.0),
+            ))
+
+
+
 def main(argv=sys.argv, stderr=sys.stderr, reactor=None):
 
     if reactor is None:
@@ -3030,6 +3180,8 @@
             return MissingLocationService(store, options, output, reactor, config)
         elif options["split"]:
             return EventSplitService(store, options, output, reactor, config)
+        elif options["upgrade"]:
+            return UpgradeDataService(store, options, output, reactor, config)
         else:
             printusage("Invalid operation")
             sys.exit(1)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20160311/7f79c1a5/attachment-0001.html>


More information about the calendarserver-changes mailing list