Commit 22943c34 authored by Andreas Jung's avatar Andreas Jung

Collector #1332: added in-place migration for

Catalog.__len__ -> Catalog._length
parent 4b02a4ea
...@@ -157,6 +157,9 @@ Zope Changes ...@@ -157,6 +157,9 @@ Zope Changes
Bugs fixed Bugs fixed
- Collector #1332: Added in-place migration of the Catalog.__len__
attribute to avoid new-style class caching problems.
- Collector #1457: ZCTextIndex's QueryError and ParseError - Collector #1457: ZCTextIndex's QueryError and ParseError
are now available for import from untrusted code. are now available for import from untrusted code.
......
...@@ -78,13 +78,7 @@ class Catalog(Persistent, Acquisition.Implicit, ExtensionClass.Base): ...@@ -78,13 +78,7 @@ class Catalog(Persistent, Acquisition.Implicit, ExtensionClass.Base):
# object unique identifier to the rid, and self.paths is a # object unique identifier to the rid, and self.paths is a
# mapping of the rid to the unique identifier. # mapping of the rid to the unique identifier.
# Note that it was unfortunate to use __len__ as the attribute self._length = BTrees.Length.Length()
# name here. New-style classes cache slot methods in C slot
# pointers. The result is that instances can't override slots.
# This is not easy to change on account of old objects with
# __len__ attr.
self.__len__ = BTrees.Length.Length()
self.clear() self.clear()
if brains is not None: if brains is not None:
...@@ -92,13 +86,16 @@ class Catalog(Persistent, Acquisition.Implicit, ExtensionClass.Base): ...@@ -92,13 +86,16 @@ class Catalog(Persistent, Acquisition.Implicit, ExtensionClass.Base):
self.updateBrains() self.updateBrains()
def __len__(self): def __len__(self):
try: return self._length()
return self.__dict__['__len__']()
except KeyError: def migrate__len__(self):
# Fallback for *really* old catalogs that don't have """ migration of old __len__ magic for Zope 2.8 """
# Length objects. if not hasattr(self, '_length'):
return len(self.data) n = self.__dict__['__len__']()
del self.__dict__['__len__']
self._length = BTrees.Length.Length(n)
def clear(self): def clear(self):
""" clear catalog """ """ clear catalog """
...@@ -106,38 +103,11 @@ class Catalog(Persistent, Acquisition.Implicit, ExtensionClass.Base): ...@@ -106,38 +103,11 @@ class Catalog(Persistent, Acquisition.Implicit, ExtensionClass.Base):
self.data = IOBTree() # mapping of rid to meta_data self.data = IOBTree() # mapping of rid to meta_data
self.uids = OIBTree() # mapping of uid to rid self.uids = OIBTree() # mapping of uid to rid
self.paths = IOBTree() # mapping of rid to uid self.paths = IOBTree() # mapping of rid to uid
self._length.set(0)
# convert old-style Catalog object to new in-place
try: self.__len__.set(0)
except AttributeError: self.__len__=BTrees.Length.Length()
for index in self.indexes.keys(): for index in self.indexes.keys():
self.getIndex(index).clear() self.getIndex(index).clear()
def _convertBTrees(self, threshold=200):
from BTrees.convert import convert
if type(self.data) is not IOBTree:
data=self.data
self.data=IOBTree()
convert(data, self.data, threshold)
self.__len__=BTrees.Length.Length(len(data))
uids=self.uids
self.uids=OIBTree()
convert(uids, self.uids, threshold)
paths=self.paths
self.paths=IOBTree()
convert(paths, self.paths, threshold)
for index in self.indexes.values():
if hasattr(index, '__of__'): index=index.__of__(self)
index._convertBTrees(threshold)
def updateBrains(self): def updateBrains(self):
self.useBrains(self._v_brains) self.useBrains(self._v_brains)
...@@ -369,9 +339,7 @@ class Catalog(Persistent, Acquisition.Implicit, ExtensionClass.Base): ...@@ -369,9 +339,7 @@ class Catalog(Persistent, Acquisition.Implicit, ExtensionClass.Base):
if index is None: # we are inserting new data if index is None: # we are inserting new data
index = self.updateMetadata(object, uid) index = self.updateMetadata(object, uid)
try: self.__len__.change(1) self._length.change(1)
except AttributeError: pass # No managed length (old-style)
self.uids[uid] = index self.uids[uid] = index
self.paths[index] = uid self.paths[index] = uid
...@@ -421,8 +389,8 @@ class Catalog(Persistent, Acquisition.Implicit, ExtensionClass.Base): ...@@ -421,8 +389,8 @@ class Catalog(Persistent, Acquisition.Implicit, ExtensionClass.Base):
del data[rid] del data[rid]
del paths[rid] del paths[rid]
del uids[uid] del uids[uid]
try: self.__len__.change(-1) self._length.change(-1)
except AttributeError: pass # No managed length
else: else:
LOG.error('uncatalogObject unsuccessfully ' LOG.error('uncatalogObject unsuccessfully '
'attempted to uncatalog an object ' 'attempted to uncatalog an object '
......
...@@ -183,6 +183,9 @@ class ZCatalog(Folder, Persistent, Implicit): ...@@ -183,6 +183,9 @@ class ZCatalog(Folder, Persistent, Implicit):
self._catalog = Catalog() self._catalog = Catalog()
def __len__(self): def __len__(self):
# Perform a migration of _catalog.__len__ to _catalog._length
# to avoid with new-style class caching issues (see #1332)
self._catalog.migrate__len__()
return len(self._catalog) return len(self._catalog)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment