[CalendarServer-changes] [2305] CalendarServer/branches/release/CalendarServer-1.3-dev/lib-patches/ Twisted

source_changes at macosforge.org source_changes at macosforge.org
Mon Apr 14 09:39:27 PDT 2008


Revision: 2305
          http://trac.macosforge.org/projects/calendarserver/changeset/2305
Author:   wsanchez at apple.com
Date:     2008-04-14 09:39:25 -0700 (Mon, 14 Apr 2008)

Log Message:
-----------
Pull up r2279 r2282 r2283 r2301 r2301: Use pickle instead of serialized XML to store xattrs

Modified Paths:
--------------
    CalendarServer/branches/release/CalendarServer-1.3-dev/lib-patches/Twisted/twisted.web2.dav.element.parser.patch
    CalendarServer/branches/release/CalendarServer-1.3-dev/lib-patches/Twisted/twisted.web2.dav.xattrprops.patch

Added Paths:
-----------
    CalendarServer/branches/release/CalendarServer-1.3-dev/lib-patches/Twisted/twisted.web2.dav.test.test_xml.patch

Modified: CalendarServer/branches/release/CalendarServer-1.3-dev/lib-patches/Twisted/twisted.web2.dav.element.parser.patch
===================================================================
--- CalendarServer/branches/release/CalendarServer-1.3-dev/lib-patches/Twisted/twisted.web2.dav.element.parser.patch	2008-04-12 03:08:28 UTC (rev 2304)
+++ CalendarServer/branches/release/CalendarServer-1.3-dev/lib-patches/Twisted/twisted.web2.dav.element.parser.patch	2008-04-14 16:39:25 UTC (rev 2305)
@@ -11,7 +11,7 @@
  import xml.dom.minidom
  import xml.sax
  
-@@ -106,6 +106,26 @@
+@@ -106,6 +106,12 @@
              "children"   : [],
          }]
  
@@ -21,54 +21,42 @@
 +        # multiple times in a document.
 +        self.unknownElementClasses = {}
 +
-+        # New-style classes keep weak references to all subclasses.
-+        # As a result, the subclasses we create continue to effect the
-+        # footprint of WebDAVUnknownElement even after they are
-+        # deallocated, up to the maximum number of subclasses that exist
-+        # simultaneously.  The number of such weak references doesn't appear
-+        # to decrease.  In order to avoid growing it unneccessarily, create a
-+        # subclass for use by this document, subclass the new class instead,
-+        # and then delete it when we're done, thereby adding only one weak
-+        # reference to WebDAVUnknownElement's list.
-+        # http://trac.macosforge.org/projects/calendarserver/ticket/101
-+        class UnknownElement (WebDAVUnknownElement):
-+            pass
-+        self.unknownElementClass = UnknownElement
-+
      def endDocument(self):
          top = self.stack[-1]
  
-@@ -115,6 +135,8 @@
+@@ -115,6 +121,7 @@
          assert len(top["children"]) is 1, "Must have exactly one root element, got %d" % len(top["children"])
  
          self.dom = WebDAVDocument(top["children"][0])
 +        del(self.unknownElementClasses)
-+        del(self.unknownElementClass)
  
      def startElementNS(self, name, qname, attributes):
          attributes_dict = {}
-@@ -125,13 +147,16 @@
+@@ -125,13 +132,17 @@
  
          tag_namespace, tag_name = name
  
 -        if (name not in elements_by_tag_name):
 -            class UnknownElement (WebDAVUnknownElement):
+-                namespace = tag_namespace
+-                name      = tag_name
+-            element_class = UnknownElement
 +        if name in elements_by_tag_name:
 +            element_class = elements_by_tag_name[name]
 +        elif name in self.unknownElementClasses:
 +            element_class = self.unknownElementClasses[name]
-+        else:
-+            class UnknownElement (self.unknownElementClass):
-                 namespace = tag_namespace
-                 name      = tag_name
-             element_class = UnknownElement
--        else:
+         else:
 -            element_class = elements_by_tag_name[name]
-+            self.unknownElementClasses[name] = UnknownElement
++            def element_class(*args, **kwargs):
++                element = WebDAVUnknownElement(*args, **kwargs)
++                element.namespace = tag_namespace
++                element.name      = tag_name
++                return element
++            self.unknownElementClasses[name] = element_class
  
          self.stack.append({
              "name"       : name,
-@@ -158,7 +183,12 @@
+@@ -158,7 +169,12 @@
          self.stack[-1]["children"].append(element)
  
      def characters(self, content):
@@ -82,7 +70,7 @@
  
      def ignorableWhitespace(self, whitespace):
          self.characters(self, whitespace)
-@@ -194,6 +224,8 @@
+@@ -194,6 +210,8 @@
              except xml.sax.SAXParseException, e:
                  raise ValueError(e)
  

Copied: CalendarServer/branches/release/CalendarServer-1.3-dev/lib-patches/Twisted/twisted.web2.dav.test.test_xml.patch (from rev 2283, CalendarServer/trunk/lib-patches/Twisted/twisted.web2.dav.test.test_xml.patch)
===================================================================
--- CalendarServer/branches/release/CalendarServer-1.3-dev/lib-patches/Twisted/twisted.web2.dav.test.test_xml.patch	                        (rev 0)
+++ CalendarServer/branches/release/CalendarServer-1.3-dev/lib-patches/Twisted/twisted.web2.dav.test.test_xml.patch	2008-04-14 16:39:25 UTC (rev 2305)
@@ -0,0 +1,88 @@
+Index: twisted/web2/dav/test/test_xml.py
+===================================================================
+--- twisted/web2/dav/test/test_xml.py	(revision 0)
++++ twisted/web2/dav/test/test_xml.py	(revision 0)
+@@ -0,0 +1,83 @@
++##
++# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
++#
++# Permission is hereby granted, free of charge, to any person obtaining a copy
++# of this software and associated documentation files (the "Software"), to deal
++# in the Software without restriction, including without limitation the rights
++# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++# copies of the Software, and to permit persons to whom the Software is
++# furnished to do so, subject to the following conditions:
++# 
++# The above copyright notice and this permission notice shall be included in all
++# copies or substantial portions of the Software.
++# 
++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++# SOFTWARE.
++##
++
++from twisted.trial import unittest
++from twisted.web2.dav import davxml
++
++class XML(unittest.TestCase):
++    """
++    XML tests.
++    """
++    def test_parse(self):
++        """
++        Simple parsing
++        """
++        doc = davxml.WebDAVDocument.fromString(
++            """<?xml version="1.0" encoding="utf-8" ?>"""
++            """<D:multistatus xmlns:D="DAV:">"""
++            """  <D:response>"""
++            """    <D:href>http://webdav.sb.aol.com/webdav/secret</D:href>"""
++            """    <D:status>HTTP/1.1 403 Forbidden</D:status>"""
++            """  </D:response>"""
++            """</D:multistatus>"""
++        )
++        self.assertEquals(
++            doc,
++            davxml.WebDAVDocument(
++                davxml.MultiStatus(
++                    davxml.Response(
++                        davxml.HRef("http://webdav.sb.aol.com/webdav/secret"),
++                        davxml.Status("HTTP/1.1 403 Forbidden"),
++                    )
++                )
++            )
++        )
++
++    def test_serialize_unserialize(self):
++        """
++        Serialization and unserialization results in equivalent document.
++        """
++        doc = davxml.WebDAVDocument(
++            davxml.MultiStatus(
++                davxml.Response(
++                    davxml.HRef("http://webdav.sb.aol.com/webdav/secret"),
++                    davxml.Status("HTTP/1.1 403 Forbidden"),
++                )
++            )
++        )
++        self.assertEquals(doc, davxml.WebDAVDocument.fromString(doc.toxml()))
++
++    def test_unknownElement(self):
++        """
++        Serialization and unserialization of unknown element.
++        """
++        doc = davxml.WebDAVDocument.fromString(
++            """<?xml version="1.0" encoding="utf-8" ?>"""
++            """<T:foo xmlns:T="http://twistedmatrix.com/"/>"""
++        )
++
++        foo = davxml.WebDAVUnknownElement()
++        foo.namespace = "http://twistedmatrix.com/"
++        foo.name = "foo"
++
++        self.assertEquals(doc, davxml.WebDAVDocument(foo))
++        self.assertEquals(doc, davxml.WebDAVDocument.fromString(doc.toxml()))

Modified: CalendarServer/branches/release/CalendarServer-1.3-dev/lib-patches/Twisted/twisted.web2.dav.xattrprops.patch
===================================================================
--- CalendarServer/branches/release/CalendarServer-1.3-dev/lib-patches/Twisted/twisted.web2.dav.xattrprops.patch	2008-04-12 03:08:28 UTC (rev 2304)
+++ CalendarServer/branches/release/CalendarServer-1.3-dev/lib-patches/Twisted/twisted.web2.dav.xattrprops.patch	2008-04-14 16:39:25 UTC (rev 2305)
@@ -2,7 +2,7 @@
 ===================================================================
 --- twisted/web2/dav/xattrprops.py	(revision 19773)
 +++ twisted/web2/dav/xattrprops.py	(working copy)
-@@ -33,12 +33,18 @@
+@@ -33,12 +33,19 @@
  
  import urllib
  import sys
@@ -11,6 +11,7 @@
 +from random import random
 +from errno import EAGAIN
 +from zlib import compress, decompress
++from cPickle import dumps as pickle, loads as unpickle, PicklingError, UnpicklingError
  
  import xattr
  
@@ -21,7 +22,7 @@
  from twisted.web2 import responsecode
  from twisted.web2.http import HTTPError, StatusResponse
  from twisted.web2.dav import davxml
-@@ -66,16 +72,8 @@
+@@ -66,16 +73,8 @@
          deadPropertyXattrPrefix = "user."
  
      def _encode(clazz, name):
@@ -40,20 +41,12 @@
          return r
  
      def _decode(clazz, name):
-@@ -97,19 +95,41 @@
+@@ -97,20 +96,51 @@
  
      def get(self, qname):
          try:
 -            value = self.attrs[self._encode(qname)]
 +            data = self.attrs[self._encode(qname)]
-+            try:
-+                value = decompress(data)
-+            except zlib.error:
-+                # Value is not compressed; data was stored by old
-+                # code.  This is easy to handle, so let's keep
-+                # compatibility here.
-+                value = data
-+            del data
          except KeyError:
              raise HTTPError(StatusResponse(
                  responsecode.NOT_FOUND,
@@ -62,20 +55,37 @@
  
 -        doc = davxml.WebDAVDocument.fromString(value)
 +        try:
-+            doc = davxml.WebDAVDocument.fromString(value)
++            return decompress(unpickle(data))
++        except UnpicklingError:
++            try:
++                # Data is not pickled; try reading as compressed XML text
++                value = decompress(data)
++            except zlib.error:
++                # Value is not compressed; try reading as XML text
++                value = data
++            del data
  
 -        return doc.root_element
-+            return doc.root_element
-+        except ValueError:
-+            msg = "Invalid property value stored on server: {%s}%s %s" % (qname[0], qname[1], value)
-+            log.err(msg)
-+            raise HTTPError(StatusResponse(responsecode.INTERNAL_SERVER_ERROR, msg))
++            try:
++                doc = davxml.WebDAVDocument.fromString(value)
++                return doc.root_element
++            except ValueError:
++                msg = "Invalid property value stored on server: {%s}%s %s" % (qname[0], qname[1], value)
++                log.err(msg)
++                raise HTTPError(StatusResponse(responsecode.INTERNAL_SERVER_ERROR, msg))
  
      def set(self, property):
 -        self.attrs[self._encode(property.qname())] = property.toxml()
 +        for n in range(20):
 +            try:
-+                self.attrs[self._encode(property.qname())] = compress(property.toxml())
++                data = compress(pickle(property))
++            except PicklingError, e:
++                log.err("Unable to pickle property %r: %s" % (property, e))
+ 
++                # Can't pickle this for some reason; fall back to XML serialization
++                data = compress(property.toxml())
++            try:
++                self.attrs[self._encode(property.qname())] = data
 +            except IOError, error:
 +                if error.errno != EAGAIN:
 +                    raise
@@ -83,6 +93,7 @@
 +            else:
 +                break
 +    
- 
++
          # Update the resource because we've modified it
          self.resource.fp.restat()
+ 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080414/59cec90b/attachment-0001.html


More information about the calendarserver-changes mailing list