<!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>[9911] CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py</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.calendarserver.org//changeset/9911">9911</a></dd>
<dt>Author</dt> <dd>gaya@apple.com</dd>
<dt>Date</dt> <dd>2012-10-09 13:13:47 -0700 (Tue, 09 Oct 2012)</dd>
</dl>
<h3>Log Message</h3>
<pre>merge in changeset/9910 from trunk</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesusersgayasharedgroupstxdavcommondatastoresqlpy">CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServerbranchesusersgayasharedgroupstxdavcommondatastoresqlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py (9910 => 9911)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py        2012-10-09 20:11:51 UTC (rev 9910)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py        2012-10-09 20:13:47 UTC (rev 9911)
</span><span class="lines">@@ -217,6 +217,7 @@
</span><span class="cx"> self._migrating = state
</span><span class="cx"> self._enableNotifications = not state
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def setUpgrading(self, state):
</span><span class="cx"> """
</span><span class="cx"> Set the "upgrading" state
</span><span class="lines">@@ -224,6 +225,7 @@
</span><span class="cx"> self._enableNotifications = not state
</span><span class="cx">
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> class TransactionStatsCollector(object):
</span><span class="cx"> """
</span><span class="cx"> Used to log each SQL query and statistics about that query during the course of a single transaction.
</span><span class="lines">@@ -235,6 +237,7 @@
</span><span class="cx"> self.logFileName = logFileName
</span><span class="cx"> self.statements = []
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def startStatement(self, sql, args):
</span><span class="cx"> """
</span><span class="cx"> Called prior to an SQL query being run.
</span><span class="lines">@@ -243,7 +246,7 @@
</span><span class="cx"> @type sql: C{str}
</span><span class="cx"> @param args: the arguments (binds) to the SQL statement
</span><span class="cx"> @type args: C{list}
</span><del>-
</del><ins>+
</ins><span class="cx"> @return: C{tuple} containing the index in the statement list for this statement, and the start time
</span><span class="cx"> """
</span><span class="cx"> args = ["%s" % (arg,) for arg in args]
</span><span class="lines">@@ -251,6 +254,7 @@
</span><span class="cx"> self.statements.append(["%s %s" % (sql, args,), 0, 0])
</span><span class="cx"> return len(self.statements) - 1, time.time()
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def endStatement(self, context, rows):
</span><span class="cx"> """
</span><span class="cx"> Called after an SQL query has executed.
</span><span class="lines">@@ -264,6 +268,7 @@
</span><span class="cx"> self.statements[index][1] = len(rows) if rows else 0
</span><span class="cx"> self.statements[index][2] = time.time() - tstamp
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def printReport(self):
</span><span class="cx"> """
</span><span class="cx"> Print a report of all the SQL statements executed to date.
</span><span class="lines">@@ -289,6 +294,8 @@
</span><span class="cx"> else:
</span><span class="cx"> log.error(toFile.getvalue())
</span><span class="cx">
</span><ins>+
+
</ins><span class="cx"> class CommonStoreTransactionMonitor(object):
</span><span class="cx"> """
</span><span class="cx"> Object that monitors the state of a transaction over time and logs or times out
</span><span class="lines">@@ -310,6 +317,7 @@
</span><span class="cx"> self._installLogTimer()
</span><span class="cx"> self._installTimeout()
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def _cleanTxn(self):
</span><span class="cx"> self.txn = None
</span><span class="cx"> if self.delayedLog:
</span><span class="lines">@@ -319,6 +327,7 @@
</span><span class="cx"> self.delayedTimeout.cancel()
</span><span class="cx"> self.delayedTimeout = None
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def _installLogTimer(self):
</span><span class="cx"> def _logTransactionWait():
</span><span class="cx"> if self.txn is not None:
</span><span class="lines">@@ -328,6 +337,7 @@
</span><span class="cx"> if self.logTimerSeconds:
</span><span class="cx"> self.delayedLog = self.callLater(self.logTimerSeconds, _logTransactionWait)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def _installTimeout(self):
</span><span class="cx"> def _forceAbort():
</span><span class="cx"> if self.txn is not None:
</span><span class="lines">@@ -444,6 +454,7 @@
</span><span class="cx"> Where=cs.NAME == Parameter('name'),
</span><span class="cx"> )
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def calendarserverValue(self, key):
</span><span class="cx"> result = yield self._calendarserver.on(self, name=key)
</span><span class="lines">@@ -507,6 +518,7 @@
</span><span class="cx"> """
</span><span class="cx"> return NotificationCollection.notificationsWithUID(self, uid, create)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classproperty
</span><span class="cx"> def _insertAPNSubscriptionQuery(cls): #@NoSelf
</span><span class="cx"> apn = schema.APN_SUBSCRIPTIONS
</span><span class="lines">@@ -648,9 +660,11 @@
</span><span class="cx"> def isNotifiedAlready(self, obj):
</span><span class="cx"> return obj in self._notifiedAlready
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def notificationAddedForObject(self, obj):
</span><span class="cx"> self._notifiedAlready.add(obj)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def isBumpedAlready(self, obj):
</span><span class="cx"> """
</span><span class="cx"> Indicates whether or not bumpAddedForObject has already been
</span><span class="lines">@@ -659,6 +673,7 @@
</span><span class="cx"> """
</span><span class="cx"> return obj in self._bumpedAlready
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def bumpAddedForObject(self, obj):
</span><span class="cx"> """
</span><span class="cx"> Records the fact that a bumpModified( ) call has already been
</span><span class="lines">@@ -754,13 +769,14 @@
</span><span class="cx"> # caller shouldn't be paying attention anyway.
</span><span class="cx"> block.end()
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def execSQL(self, *a, **kw):
</span><span class="cx"> """
</span><span class="cx"> Execute some SQL (delegate to L{IAsyncTransaction}).
</span><span class="cx"> """
</span><span class="cx"> if self._stats:
</span><del>- statsContext = self._stats.startStatement(a[0], a[1])
</del><ins>+ statsContext = self._stats.startStatement(a[0], a[1] if len(a) > 1 else ())
</ins><span class="cx"> self.currentStatement = a[0]
</span><span class="cx"> if self._store.logTransactionWaits and a[0].split(" ", 1)[0].lower() in ("insert", "update", "delete",):
</span><span class="cx"> self.iudCount += 1
</span><span class="lines">@@ -777,14 +793,15 @@
</span><span class="cx"> self._stats.endStatement(statsContext, results)
</span><span class="cx"> returnValue(results)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def execSQLBlock(self, sql):
</span><span class="cx"> """
</span><span class="cx"> Execute a block of SQL by parsing it out into individual statements and execute
</span><span class="cx"> each of those.
</span><del>-
</del><ins>+
</ins><span class="cx"> FIXME: temporary measure for handling large schema upgrades. This should NOT be used
</span><del>- for regular SQL operations - only upgrades.
</del><ins>+ for regular SQL operations - only upgrades.
</ins><span class="cx"> """
</span><span class="cx"> parsed = parse(sql)
</span><span class="cx"> for stmt in parsed:
</span><span class="lines">@@ -795,6 +812,7 @@
</span><span class="cx"> stmt = str(stmt).rstrip(";")
</span><span class="cx"> yield self.execSQL(stmt)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def commit(self):
</span><span class="cx"> """
</span><span class="cx"> Commit the transaction and execute any post-commit hooks.
</span><span class="lines">@@ -816,7 +834,7 @@
</span><span class="cx"> co = schema.CALENDAR_OBJECT
</span><span class="cx"> cb = schema.CALENDAR_BIND
</span><span class="cx"> tr = schema.TIME_RANGE
</span><del>- kwds = { }
</del><ins>+ kwds = {}
</ins><span class="cx"> if limited:
</span><span class="cx"> kwds["Limit"] = Parameter("batchSize")
</span><span class="cx"> return Select(
</span><span class="lines">@@ -864,7 +882,7 @@
</span><span class="cx"> if cutoff < truncateLowerLimit:
</span><span class="cx"> raise ValueError("Cannot query events older than %s" % (truncateLowerLimit.getText(),))
</span><span class="cx">
</span><del>- kwds = { "CutOff" : pyCalendarTodatetime(cutoff) }
</del><ins>+ kwds = {"CutOff": pyCalendarTodatetime(cutoff)}
</ins><span class="cx"> if batchSize is not None:
</span><span class="cx"> kwds["batchSize"] = batchSize
</span><span class="cx"> query = self._oldEventsLimited
</span><span class="lines">@@ -948,15 +966,22 @@
</span><span class="cx"> returnValue(count)
</span><span class="cx">
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> class _EmptyCacher(object):
</span><ins>+
</ins><span class="cx"> def set(self, key, value):
</span><span class="cx"> return succeed(True)
</span><ins>+
+
</ins><span class="cx"> def get(self, key, withIdentifier=False):
</span><span class="cx"> return succeed(None)
</span><ins>+
+
</ins><span class="cx"> def delete(self, key):
</span><span class="cx"> return succeed(True)
</span><span class="cx">
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> class CommonHome(LoggingMixIn):
</span><span class="cx">
</span><span class="cx"> # All these need to be initialized by derived classes for each store type
</span><span class="lines">@@ -1017,6 +1042,7 @@
</span><span class="cx"> return Select([home.RESOURCE_ID],
</span><span class="cx"> From=home, Where=home.OWNER_UID == Parameter("ownerUID"))
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classproperty
</span><span class="cx"> def _ownerFromResourceID(cls): #@NoSelf
</span><span class="cx"> home = cls._homeSchema
</span><span class="lines">@@ -1024,6 +1050,7 @@
</span><span class="cx"> From=home,
</span><span class="cx"> Where=home.RESOURCE_ID == Parameter("resourceID"))
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classproperty
</span><span class="cx"> def _metaDataQuery(cls): #@NoSelf
</span><span class="cx"> metadata = cls._homeMetaDataSchema
</span><span class="lines">@@ -1031,6 +1058,7 @@
</span><span class="cx"> From=metadata,
</span><span class="cx"> Where=metadata.RESOURCE_ID == Parameter("resourceID"))
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def initFromStore(self, no_cache=False):
</span><span class="cx"> """
</span><span class="lines">@@ -1183,6 +1211,7 @@
</span><span class="cx"> self._childrenLoaded = True
</span><span class="cx"> returnValue(results)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def listChildren(self):
</span><span class="cx"> """
</span><span class="cx"> Retrieve the names of the children in this home.
</span><span class="lines">@@ -1216,6 +1245,7 @@
</span><span class="cx"> """
</span><span class="cx"> return self._childClass.objectWithName(self, name)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @memoizedKey("resourceID", "_children")
</span><span class="cx"> def childWithID(self, resourceID):
</span><span class="cx"> """
</span><span class="lines">@@ -1227,6 +1257,7 @@
</span><span class="cx"> """
</span><span class="cx"> return self._childClass.objectWithID(self, resourceID)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def invitedChildWithName(self, name):
</span><span class="cx"> """
</span><span class="cx"> Retrieve the invited child with the given C{name} contained in this
</span><span class="lines">@@ -1237,6 +1268,7 @@
</span><span class="cx"> """
</span><span class="cx"> return self._childClass.invitedObjectWithName(self, name)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def createChildWithName(self, name):
</span><span class="cx"> if name.startswith("."):
</span><span class="lines">@@ -1246,6 +1278,7 @@
</span><span class="cx"> child = (yield self.childWithName(name))
</span><span class="cx"> returnValue(child)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def removeChildWithName(self, name):
</span><span class="cx"> child = yield self.childWithName(name)
</span><span class="lines">@@ -1575,6 +1608,7 @@
</span><span class="cx"> else:
</span><span class="cx"> returnValue(None)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classproperty
</span><span class="cx"> def _lockLastModifiedQuery(cls): #@NoSelf
</span><span class="cx"> meta = cls._homeMetaDataSchema
</span><span class="lines">@@ -1585,6 +1619,7 @@
</span><span class="cx"> NoWait=True
</span><span class="cx"> )
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classproperty
</span><span class="cx"> def _changeLastModifiedQuery(cls): #@NoSelf
</span><span class="cx"> meta = cls._homeMetaDataSchema
</span><span class="lines">@@ -1592,6 +1627,7 @@
</span><span class="cx"> Where=meta.RESOURCE_ID == Parameter("resourceID"),
</span><span class="cx"> Return=meta.MODIFIED)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def bumpModified(self):
</span><span class="cx"> """
</span><span class="lines">@@ -1625,6 +1661,7 @@
</span><span class="cx"> except AllRetriesFailed:
</span><span class="cx"> log.debug("CommonHome.bumpModified failed")
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def notifyChanged(self):
</span><span class="cx"> """
</span><span class="lines">@@ -1677,6 +1714,7 @@
</span><span class="cx"> _ignore_uuid, revision = token.split("_", 1)
</span><span class="cx"> return int(revision)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def syncToken(self):
</span><span class="cx"> if self._syncTokenRevision is None:
</span><span class="lines">@@ -1715,7 +1753,7 @@
</span><span class="cx"> (yield self._objectNamesSinceRevisionQuery.on(
</span><span class="cx"> self._txn, revision=token, resourceID=self._resourceID))
</span><span class="cx"> ]
</span><del>- results.sort(key=lambda x:x[1])
</del><ins>+ results.sort(key=lambda x: x[1])
</ins><span class="cx">
</span><span class="cx"> changed = []
</span><span class="cx"> deleted = []
</span><span class="lines">@@ -2034,6 +2072,7 @@
</span><span class="cx"> cls._homeChildMetaDataSchema.MODIFIED,
</span><span class="cx"> )
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classmethod
</span><span class="cx"> def metadataAttributes(cls):
</span><span class="cx"> """
</span><span class="lines">@@ -2049,6 +2088,7 @@
</span><span class="cx"> "_modified",
</span><span class="cx"> )
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classmethod
</span><span class="cx"> @inlineCallbacks
</span><span class="cx"> def listObjects(cls, home):
</span><span class="lines">@@ -2070,6 +2110,7 @@
</span><span class="cx"> return cls._bindFor((bind.HOME_RESOURCE_ID == Parameter("homeID"))
</span><span class="cx"> .And(bind.BIND_STATUS != _BIND_STATUS_ACCEPTED))
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classmethod
</span><span class="cx"> @inlineCallbacks
</span><span class="cx"> def listInvitedObjects(cls, home):
</span><span class="lines">@@ -2112,11 +2153,11 @@
</span><span class="cx"> def _updateBindColumnsQuery(cls, columnMap): #@NoSelf
</span><span class="cx"> bind = cls._bindSchema
</span><span class="cx"> return Update(columnMap,
</span><del>- Where=
- (bind.RESOURCE_ID == Parameter("resourceID"))
</del><ins>+ Where=(bind.RESOURCE_ID == Parameter("resourceID"))
</ins><span class="cx"> .And(bind.HOME_RESOURCE_ID == Parameter("homeID")),
</span><span class="cx"> Return=bind.RESOURCE_NAME)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classproperty
</span><span class="cx"> def _updateBindQuery(cls): #@NoSelf
</span><span class="cx"> bind = cls._bindSchema
</span><span class="lines">@@ -2235,7 +2276,7 @@
</span><span class="cx"> if shareeView._bindStatus == _BIND_STATUS_ACCEPTED:
</span><span class="cx"> yield shareeView._initSyncToken()
</span><span class="cx"> elif shareeView._bindStatus == _BIND_STATUS_DECLINED:
</span><del>- shareeView._deletedSyncToken(sharedRemoval=True);
</del><ins>+ shareeView._deletedSyncToken(sharedRemoval=True)
</ins><span class="cx">
</span><span class="cx"> if message:
</span><span class="cx"> shareeView._bindMessage = columnMap[bind.MESSAGE]
</span><span class="lines">@@ -2253,7 +2294,6 @@
</span><span class="cx"> returnValue(shareeView._name)
</span><span class="cx">
</span><span class="cx">
</span><del>-
</del><span class="cx"> @inlineCallbacks
</span><span class="cx"> def unshareWith(self, shareeHome):
</span><span class="cx"> """
</span><span class="lines">@@ -2268,19 +2308,18 @@
</span><span class="cx"> @return: a L{Deferred} which will fire with the previously-used name.
</span><span class="cx"> """
</span><span class="cx">
</span><del>-
</del><span class="cx"> #remove sync tokens
</span><span class="cx"> shareeChildren = yield shareeHome.children()
</span><span class="cx"> for shareeChild in shareeChildren:
</span><span class="cx"> if not shareeChild.owned() and shareeChild._resourceID == self._resourceID:
</span><del>- shareeChild._deletedSyncToken(sharedRemoval=True);
</del><ins>+ shareeChild._deletedSyncToken(sharedRemoval=True)
</ins><span class="cx">
</span><span class="cx"> queryCacher = self._txn._queryCacher
</span><span class="cx"> if queryCacher:
</span><span class="cx"> cacheKey = queryCacher.keyForObjectWithName(shareeHome._resourceID, shareeChild._name)
</span><span class="cx"> queryCacher.invalidateAfterCommit(self._txn, cacheKey)
</span><span class="cx">
</span><del>- break;
</del><ins>+ break
</ins><span class="cx">
</span><span class="cx"> bind = self._bindSchema
</span><span class="cx"> rows = yield Delete(
</span><span class="lines">@@ -2308,30 +2347,35 @@
</span><span class="cx"> """
</span><span class="cx"> return self._bindMode
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def owned(self):
</span><span class="cx"> """
</span><span class="cx"> @see: L{ICalendar.owned}
</span><span class="cx"> """
</span><span class="cx"> return self._bindMode == _BIND_MODE_OWN
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def shareStatus(self):
</span><span class="cx"> """
</span><span class="cx"> @see: L{ICalendar.shareStatus}
</span><span class="cx"> """
</span><span class="cx"> return self._bindStatus
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def shareMessage(self):
</span><span class="cx"> """
</span><span class="cx"> @see: L{ICalendar.shareMessage}
</span><span class="cx"> """
</span><span class="cx"> return self._bindMessage
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def shareUID(self):
</span><span class="cx"> """
</span><span class="cx"> @see: L{ICalendar.shareUID}
</span><span class="cx"> """
</span><span class="cx"> return self.name()
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def unshare(self, homeType):
</span><span class="cx"> """
</span><span class="lines">@@ -2366,6 +2410,7 @@
</span><span class="cx"> Where=condition
</span><span class="cx"> )
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classproperty
</span><span class="cx"> def _sharedBindForResourceID(cls): #@NoSelf
</span><span class="cx"> bind = cls._bindSchema
</span><span class="lines">@@ -2375,7 +2420,6 @@
</span><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><del>-
</del><span class="cx"> @inlineCallbacks
</span><span class="cx"> def asShared(self):
</span><span class="cx"> """
</span><span class="lines">@@ -2420,6 +2464,7 @@
</span><span class="cx"> .And(bind.BIND_STATUS != _BIND_STATUS_ACCEPTED)
</span><span class="cx"> )
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def asInvited(self):
</span><span class="cx"> """
</span><span class="lines">@@ -2573,6 +2618,7 @@
</span><span class="cx"> .And(bind.BIND_STATUS == _BIND_STATUS_ACCEPTED)
</span><span class="cx"> )
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classmethod
</span><span class="cx"> @inlineCallbacks
</span><span class="cx"> def objectWithName(cls, home, name):
</span><span class="lines">@@ -2602,7 +2648,7 @@
</span><span class="cx">
</span><span class="cx"> if rows:
</span><span class="cx"> bindMode, homeID, resourceID, resourceName, bindStatus, bindMessage = rows[0] #@UnusedVariable
</span><del>- # get ownerHomeID
</del><ins>+ # get ownerHomeID
</ins><span class="cx"> if bindMode == _BIND_MODE_OWN:
</span><span class="cx"> ownerHomeID = homeID
</span><span class="cx"> else:
</span><span class="lines">@@ -3164,6 +3210,7 @@
</span><span class="cx"> raise NoSuchObjectResourceError
</span><span class="cx"> yield self._removeObjectResource(child)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def _removeObjectResource(self, child):
</span><span class="cx"> name = child.name()
</span><span class="lines">@@ -3176,6 +3223,7 @@
</span><span class="cx"> yield self._deleteRevision(name)
</span><span class="cx"> yield self.notifyChanged()
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classproperty
</span><span class="cx"> def _moveParentUpdateQuery(cls): #@NoSelf
</span><span class="cx"> """
</span><span class="lines">@@ -3187,6 +3235,7 @@
</span><span class="cx"> Where=obj.RESOURCE_ID == Parameter("resourceID")
</span><span class="cx"> )
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def _movedObjectResource(self, child, newparent):
</span><span class="cx"> """
</span><span class="cx"> Method that subclasses can override to do an extra DB adjustments when a resource
</span><span class="lines">@@ -3194,12 +3243,13 @@
</span><span class="cx"> """
</span><span class="cx"> return succeed(True)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def moveObjectResource(self, child, newparent):
</span><span class="cx"> """
</span><span class="cx"> Move a child of this collection into another collection without actually removing/re-inserting the data.
</span><span class="cx"> Make sure sync and cache details for both collections are updated.
</span><del>-
</del><ins>+
</ins><span class="cx"> TODO: check that the resource name does not exist in the new parent, or that the UID
</span><span class="cx"> does not exist there too.
</span><span class="cx">
</span><span class="lines">@@ -3232,6 +3282,7 @@
</span><span class="cx"> yield newparent._insertRevision(name)
</span><span class="cx"> yield newparent.notifyChanged()
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def objectResourcesHaveProperties(self):
</span><span class="cx"> return False
</span><span class="cx">
</span><span class="lines">@@ -3261,6 +3312,7 @@
</span><span class="cx">
</span><span class="cx"> @param props: the L{PropertyStore} from C{properties()}.
</span><span class="cx"> """
</span><ins>+ pass
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> # IDataStoreObject
</span><span class="lines">@@ -3289,12 +3341,14 @@
</span><span class="cx"> self._notifiers = ()
</span><span class="cx"> self._notifiers += (notifier,)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def notifierID(self, label="default"):
</span><span class="cx"> if self._notifiers:
</span><span class="cx"> return self._notifiers[0].getID(label)
</span><span class="cx"> else:
</span><span class="cx"> return None
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def nodeName(self, label="default"):
</span><span class="cx"> if self._notifiers:
</span><span class="lines">@@ -3305,6 +3359,7 @@
</span><span class="cx"> else:
</span><span class="cx"> returnValue(None)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classproperty
</span><span class="cx"> def _lockLastModifiedQuery(cls): #@NoSelf
</span><span class="cx"> schema = cls._homeChildMetaDataSchema
</span><span class="lines">@@ -3315,6 +3370,7 @@
</span><span class="cx"> NoWait=True
</span><span class="cx"> )
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classproperty
</span><span class="cx"> def _changeLastModifiedQuery(cls): #@NoSelf
</span><span class="cx"> schema = cls._homeChildMetaDataSchema
</span><span class="lines">@@ -3353,6 +3409,7 @@
</span><span class="cx"> except AllRetriesFailed:
</span><span class="cx"> log.debug("CommonHomeChild.bumpModified failed")
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def notifyChanged(self):
</span><span class="cx"> """
</span><span class="lines">@@ -3370,6 +3427,7 @@
</span><span class="cx"> self._txn.notificationAddedForObject(self)
</span><span class="cx">
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> class CommonObjectResource(LoggingMixIn, FancyEqMixin):
</span><span class="cx"> """
</span><span class="cx"> Base class for object resources.
</span><span class="lines">@@ -3447,6 +3505,7 @@
</span><span class="cx">
</span><span class="cx"> returnValue(results)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classmethod
</span><span class="cx"> def _allColumnsWithParentAndNames(cls, names): #@NoSelf
</span><span class="cx"> obj = cls._objectSchema
</span><span class="lines">@@ -3470,6 +3529,7 @@
</span><span class="cx">
</span><span class="cx"> returnValue(results)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classmethod
</span><span class="cx"> @inlineCallbacks
</span><span class="cx"> def _loadAllObjectsWithNames(cls, parent, names):
</span><span class="lines">@@ -3519,11 +3579,13 @@
</span><span class="cx"> objectResource = cls(parent, name, uid, None)
</span><span class="cx"> return objectResource.initFromStore()
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classmethod
</span><span class="cx"> def objectWithID(cls, parent, resourceID):
</span><span class="cx"> objectResource = cls(parent, None, None, resourceID)
</span><span class="cx"> return objectResource.initFromStore()
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classmethod
</span><span class="cx"> @inlineCallbacks
</span><span class="cx"> def create(cls, parent, name, component, metadata):
</span><span class="lines">@@ -3700,7 +3762,7 @@
</span><span class="cx"> @type wait: C{bool}
</span><span class="cx"> @param txn: alternative transaction to use
</span><span class="cx"> @type txn: L{CommonStoreTransaction}
</span><del>-
</del><ins>+
</ins><span class="cx"> @raise: L{NoSuchObjectResourceError} if resource does not exist, other L{Exception}
</span><span class="cx"> if already locked and NOWAIT is used.
</span><span class="cx"> """
</span><span class="lines">@@ -3722,6 +3784,7 @@
</span><span class="cx"> def componentType(self):
</span><span class="cx"> returnValue((yield self.component()).mainType())
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classproperty
</span><span class="cx"> def _deleteQuery(cls): #@NoSelf
</span><span class="cx"> """
</span><span class="lines">@@ -3746,6 +3809,7 @@
</span><span class="cx"> self._modified = None
</span><span class="cx"> self._objectText = None
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def uid(self):
</span><span class="cx"> return self._uid
</span><span class="cx">
</span><span class="lines">@@ -3754,7 +3818,6 @@
</span><span class="cx"> return self._name
</span><span class="cx">
</span><span class="cx">
</span><del>-
</del><span class="cx"> # IDataStoreObject
</span><span class="cx"> def contentType(self):
</span><span class="cx"> raise NotImplementedError()
</span><span class="lines">@@ -3842,12 +3905,10 @@
</span><span class="cx"> notifiers = None
</span><span class="cx"> self._notifiers = notifiers
</span><span class="cx">
</span><del>-
</del><span class="cx"> _resourceIDFromUIDQuery = Select(
</span><span class="cx"> [_homeSchema.RESOURCE_ID], From=_homeSchema,
</span><span class="cx"> Where=_homeSchema.OWNER_UID == Parameter("uid"))
</span><span class="cx">
</span><del>-
</del><span class="cx"> _provisionNewNotificationsQuery = Insert(
</span><span class="cx"> {_homeSchema.OWNER_UID: Parameter("uid")},
</span><span class="cx"> Return=_homeSchema.RESOURCE_ID
</span><span class="lines">@@ -3951,7 +4012,6 @@
</span><span class="cx"> self._notificationNames = sorted([result.name() for result in results])
</span><span class="cx"> returnValue(results)
</span><span class="cx">
</span><del>-
</del><span class="cx"> _notificationUIDsForHomeQuery = Select(
</span><span class="cx"> [schema.NOTIFICATION.NOTIFICATION_UID], From=schema.NOTIFICATION,
</span><span class="cx"> Where=schema.NOTIFICATION.NOTIFICATION_HOME_RESOURCE_ID ==
</span><span class="lines">@@ -4009,7 +4069,6 @@
</span><span class="cx"> def removeNotificationObjectWithName(self, name):
</span><span class="cx"> return self.removeNotificationObjectWithUID(self._nameToUID(name))
</span><span class="cx">
</span><del>-
</del><span class="cx"> _removeByUIDQuery = Delete(
</span><span class="cx"> From=schema.NOTIFICATION,
</span><span class="cx"> Where=(schema.NOTIFICATION.NOTIFICATION_UID == Parameter("uid")).And(
</span><span class="lines">@@ -4024,7 +4083,6 @@
</span><span class="cx"> self._notifications.pop(uid, None)
</span><span class="cx"> yield self._deleteRevision("%s.xml" % (uid,))
</span><span class="cx">
</span><del>-
</del><span class="cx"> _initSyncTokenQuery = Insert(
</span><span class="cx"> {
</span><span class="cx"> _revisionsSchema.HOME_RESOURCE_ID : Parameter("resourceID"),
</span><span class="lines">@@ -4040,7 +4098,6 @@
</span><span class="cx"> self._syncTokenRevision = (yield self._initSyncTokenQuery.on(
</span><span class="cx"> self._txn, resourceID=self._resourceID))[0][0]
</span><span class="cx">
</span><del>-
</del><span class="cx"> _syncTokenQuery = Select(
</span><span class="cx"> [Max(_revisionsSchema.REVISION)], From=_revisionsSchema,
</span><span class="cx"> Where=_revisionsSchema.HOME_RESOURCE_ID == Parameter("resourceID")
</span><span class="lines">@@ -4066,6 +4123,7 @@
</span><span class="cx"> self._notifiers = ()
</span><span class="cx"> self._notifiers += (notifier,)
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def notifierID(self, label="default"):
</span><span class="cx"> if self._notifiers:
</span><span class="cx"> return self._notifiers[0].getID(label)
</span><span class="lines">@@ -4121,7 +4179,7 @@
</span><span class="cx"> """
</span><span class="cx"> # Delete NOTIFICATION rows
</span><span class="cx"> no = schema.NOTIFICATION
</span><del>- kwds = { "ResourceID" : self._resourceID }
</del><ins>+ kwds = {"ResourceID": self._resourceID}
</ins><span class="cx"> yield Delete(
</span><span class="cx"> From=no,
</span><span class="cx"> Where=(
</span><span class="lines">@@ -4139,6 +4197,7 @@
</span><span class="cx"> ).on(self._txn, **kwds)
</span><span class="cx">
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> class NotificationObject(LoggingMixIn, FancyEqMixin):
</span><span class="cx">
</span><span class="cx"> implements(INotificationObject)
</span><span class="lines">@@ -4348,7 +4407,6 @@
</span><span class="cx"> self._modified = rows[0][0]
</span><span class="cx"> self._objectText = xmldata
</span><span class="cx">
</span><del>-
</del><span class="cx"> _xmlDataFromID = Select(
</span><span class="cx"> [_objectSchema.XML_DATA], From=_objectSchema,
</span><span class="cx"> Where=_objectSchema.RESOURCE_ID == Parameter("resourceID"))
</span><span class="lines">@@ -4377,6 +4435,7 @@
</span><span class="cx"> def size(self):
</span><span class="cx"> return self._size
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def xmlType(self):
</span><span class="cx"> # NB This is the NotificationType property element
</span><span class="cx"> if isinstance(self._xmlType, str):
</span><span class="lines">@@ -4385,6 +4444,7 @@
</span><span class="cx">
</span><span class="cx"> return self._xmlType
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def created(self):
</span><span class="cx"> return datetimeMktime(parseSQLTimestamp(self._created))
</span><span class="cx">
</span><span class="lines">@@ -4744,6 +4804,3 @@
</span><span class="cx"> # obscure bug.
</span><span class="cx"> else:
</span><span class="cx"> yield t.commit()
</span><del>-
-
-
</del></span></pre>
</div>
</div>
</body>
</html>