[CalendarServer-changes] [1195]
CalendarServer/branches/users/cdaboo/sqlprops-1126/twistedcaldav
source_changes at macosforge.org
source_changes at macosforge.org
Fri Feb 16 11:00:45 PST 2007
Revision: 1195
http://trac.macosforge.org/projects/calendarserver/changeset/1195
Author: cdaboo at apple.com
Date: 2007-02-16 11:00:45 -0800 (Fri, 16 Feb 2007)
Log Message:
-----------
Add methods for "batch" queries on multiple properties and across multiple resources.
Modified Paths:
--------------
CalendarServer/branches/users/cdaboo/sqlprops-1126/twistedcaldav/sqlprops.py
CalendarServer/branches/users/cdaboo/sqlprops-1126/twistedcaldav/test/test_sqlprops.py
Modified: CalendarServer/branches/users/cdaboo/sqlprops-1126/twistedcaldav/sqlprops.py
===================================================================
--- CalendarServer/branches/users/cdaboo/sqlprops-1126/twistedcaldav/sqlprops.py 2007-02-15 19:33:00 UTC (rev 1194)
+++ CalendarServer/branches/users/cdaboo/sqlprops-1126/twistedcaldav/sqlprops.py 2007-02-16 19:00:45 UTC (rev 1195)
@@ -44,15 +44,13 @@
class sqlPropertyStore (object):
"""
-
+ A dead property store that uses an SQLite database backend.
"""
def _encode(clazz, name):
- return urllib.quote("{%s}%s" % name, safe='{}:')
+ return "{%s}%s" % name
def _decode(clazz, name):
- name = urllib.unquote(name)
-
index = name.find("}")
if (index is -1 or not len(name) > index or not name[0] == "{"):
@@ -99,6 +97,58 @@
return doc.root_element
+ def getAll(self, qnames):
+ """
+ Read properties from index.
+
+ @param qnames: C{list} of C{tuple} of property namespace and name.
+ @return: a C{list} of property classes
+ """
+ if not qnames:
+ return None
+
+ if not self.index:
+ raise HTTPError(StatusResponse(
+ responsecode.NOT_FOUND,
+ "No such property: {%s}%s" % qnames[0]
+ ))
+
+ values = self.index.getAllPropertyValues(self.rname, map(self._encode, qnames))
+
+ results = []
+ for value in values.itervalues():
+ doc = davxml.WebDAVDocument.fromString(value)
+ results.append(doc.root_element)
+ return results
+
+ def getAllResources(self, qnames):
+ """
+ Read properties for all child resources from index.
+
+ @param qnames: C{list} of C{tuple} of property namespace and name.
+ @return: a C{dict} with resource name as keys and C{list} of property classes as values
+ """
+ if not qnames:
+ return None
+
+ if not self.index:
+ raise HTTPError(StatusResponse(
+ responsecode.NOT_FOUND,
+ "No such property: {%s}%s" % qnames[0]
+ ))
+
+ values = self.index.getAllResourcePropertyValues(map(self._encode, qnames))
+ results = {}
+
+ for key, value in values.iteritems():
+ pvalues = []
+ for pvalue in value.itervalues():
+ doc = davxml.WebDAVDocument.fromString(pvalue)
+ pvalues.append(doc.root_element)
+ results[key] = pvalues
+
+ return results
+
def set(self, property):
"""
Write property into index.
@@ -150,8 +200,7 @@
if self.index:
results = self.index.listProperties(self.rname)
- result = [self._decode(name) for name in results]
- return result
+ return map(self._decode, results)
else:
return []
@@ -210,8 +259,57 @@
return members[0]
else:
raise ValueError("Multiple properties of the same name %s stored for resource %s" % (pname, rname,))
+
+ def getAllPropertyValues(self, rname, pnames):
+ """
+ Get specified property values from specific resource.
+
+ @param rname: a C{str} containing the resource name.
+ @param pnames: a C{list} of C{str} containing the name of the properties to get.
+ @return: a C{dict} containing property name/value.
+ """
+ # Remove what is there, then add it back.
+ log.msg("getAllPropertyValues: %s \"%s\"" % (self.dbpath, pnames))
+ properties = {}
+ statement = "select PROPERTYNAME, PROPERTYVALUE from PROPERTIES where RESOURCENAME = :1 and ("
+ args = [rname]
+ for i, pname in enumerate(pnames):
+ if i != 0:
+ statement += " or "
+ statement += "PROPERTYNAME=:%s" % (i + 2,)
+ args.append(pname)
+ statement += ")"
+ for row in self._db_execute(statement, *args):
+ properties[row[0]] = row[1]
+
+ return properties
+
+ def getAllResourcePropertyValues(self, pnames):
+ """
+ Get specified property values from all resources.
+
+ @param pnames: a C{list} of C{str} containing the name of the properties to get.
+ @return: a C{dict} containing C{str} keys (names of child resources) and C{dict} values of property name/value.
+ """
+
+ # Remove what is there, then add it back.
+ log.msg("getAllPropertyValues: %s \"%s\"" % (self.dbpath, pnames))
+ members = {}
+ statement = "select RESOURCENAME, PROPERTYNAME, PROPERTYVALUE from PROPERTIES where "
+ args = []
+ for i, pname in enumerate(pnames):
+ if i != 0:
+ statement += " or "
+ statement += "PROPERTYNAME=:%s" % (i + 1,)
+ args.append(pname)
+
+ for row in self._db_execute(statement, *args):
+ members.setdefault(row[0], {})[row[1]] = row[2]
+
+ return members
+
def removeProperty(self, rname, pname):
"""
Remove a property.
Modified: CalendarServer/branches/users/cdaboo/sqlprops-1126/twistedcaldav/test/test_sqlprops.py
===================================================================
--- CalendarServer/branches/users/cdaboo/sqlprops-1126/twistedcaldav/test/test_sqlprops.py 2007-02-15 19:33:00 UTC (rev 1194)
+++ CalendarServer/branches/users/cdaboo/sqlprops-1126/twistedcaldav/test/test_sqlprops.py 2007-02-16 19:00:45 UTC (rev 1195)
@@ -15,6 +15,8 @@
#
# DRI: Wilfredo Sanchez, wsanchez at apple.com
##
+import time
+from twistedcaldav.root import RootResource
from twistedcaldav import customxml
from twistedcaldav import caldavxml
from twisted.web2.dav import davxml
@@ -68,12 +70,49 @@
msg="Could not find property %s." % prop)
self.assertTrue(index.get(prop.qname()) == prop,
msg="Could not get property %s." % prop)
-
+
+ def _testPropertyList(self, proplist):
+ self.assertTrue(len(proplist) == len(SQLProps.props),
+ msg="Number of properties returned %s not equal to number queried %s." % (len(proplist), len(SQLProps.props),))
+ for prop in SQLProps.props:
+ for p in proplist:
+ if prop == p:
+ proplist.remove(p)
+ break
+ self.assertTrue(len(proplist) == 0,
+ msg="Incorrect properties returned %s." % proplist)
+
+ def _testResourcePropertyList(self, num_resources, resourcedict):
+ self.assertTrue(len(resourcedict) == num_resources,
+ msg="Number of resources returned %s not equal to number queried %s." % (len(resourcedict), num_resources,))
+ for i in xrange(num_resources):
+ fname = "file%04s.ics" % (i,)
+ self.assertTrue(resourcedict.has_key(fname),
+ msg="Resource %s not returned in query results" % (fname,))
+ self._testPropertyList(resourcedict[fname])
+
+ def _setupMultipleResources(self, number):
+ self.collection_name, self.collection_uri = self.mkdtemp("sql")
+ for i in xrange(number):
+ rsrc = CalDAVFile(os.path.join(self.collection_name, "file%04s.ics" % (i,)))
+ index = sqlPropertyStore(rsrc)
+ for prop in SQLProps.props:
+ index.set(prop)
+ return index
+
def test_db_init_directory(self):
self.collection_name, self.collection_uri = self.mkdtemp("sql")
rsrc = CalDAVFile(self.collection_name)
index = sqlPropertyStore(rsrc)
db = index.index._db()
+ self.assertTrue(os.path.exists(os.path.join(os.path.dirname(self.collection_name), SQLPropertiesDatabase.dbFilename)),
+ msg="Could not initialize index via collection resource.")
+
+ def test_db_init_root(self):
+ self.collection_name, self.collection_uri = self.mkdtemp("sql")
+ rsrc = RootResource(self.collection_name)
+ index = sqlPropertyStore(rsrc)
+ db = index.index._db()
self.assertTrue(os.path.exists(os.path.join(self.collection_name, SQLPropertiesDatabase.dbFilename)),
msg="Could not initialize index via collection resource.")
@@ -121,3 +160,28 @@
for prop in SQLProps.props:
self.assertFalse(index.contains(prop.qname()),
msg="Could not find property %s." % prop)
+
+ def test_getallproperties(self):
+ index = self._setUpIndex()
+ for prop in SQLProps.props:
+ self._setProperty(index, prop)
+
+ result = index.getAll([p.qname() for p in SQLProps.props])
+ self._testPropertyList(result)
+
+ def test_getallresourceproperties(self):
+ num_resources = 10
+ index = self._setupMultipleResources(num_resources)
+ result = index.getAllResources([p.qname() for p in SQLProps.props])
+ self._testResourcePropertyList(num_resources, result)
+
+# def test_timegetallresourceproperties(self):
+# num_resources = 1000
+# index = self._setupMultipleResources(num_resources)
+# t1 = time.time()
+# result = index.getAllResources([p.qname() for p in SQLProps.props])
+# t2 = time.time()
+# self.assertTrue(t1 == t2,
+# msg="Time for 1000 prop query = %s" % (t2 - t1,))
+#
+# self._testResourcePropertyList(num_resources, result)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20070216/45660d33/attachment.html
More information about the calendarserver-changes
mailing list