[Zope-Checkins] CVS: Zope/lib/python/ZODB - serialize.py:1.2
BaseStorage.py:1.37 ConflictResolution.py:1.21
Connection.py:1.102 DB.py:1.57 DemoStorage.py:1.22
ExportImport.py:1.18 FileStorage.py:1.140
MappingStorage.py:1.10 Mount.py:1.21 POSException.py:1.22
Transaction.py:1.55 __init__.py:1.26 conversionhack.py:1.5
coptimizations.c:1.24 fsIndex.py:1.5 fsdump.py:1.14
fspack.py:1.14 fsrecover.py:1.14 fstools.py:1.2 utils.py:1.19
PersistentList.py:NONE PersistentMapping.py:NONE
cPersistence.c:NONE cPersistence.h:NONE
Jim Fulton
cvs-admin at zope.org
Fri Nov 28 11:45:24 EST 2003
Update of /cvs-repository/Zope/lib/python/ZODB
In directory cvs.zope.org:/tmp/cvs-serv3783/lib/python/ZODB
Modified Files:
BaseStorage.py ConflictResolution.py Connection.py DB.py
DemoStorage.py ExportImport.py FileStorage.py
MappingStorage.py Mount.py POSException.py Transaction.py
__init__.py conversionhack.py coptimizations.c fsIndex.py
fsdump.py fspack.py fsrecover.py fstools.py utils.py
Added Files:
serialize.py
Removed Files:
PersistentList.py PersistentMapping.py cPersistence.c
cPersistence.h
Log Message:
Merged Jeremy and Tim's changes from the zodb33-devel-branch.
=== Zope/lib/python/ZODB/serialize.py 1.1 => 1.2 ===
--- /dev/null Fri Nov 28 11:45:24 2003
+++ Zope/lib/python/ZODB/serialize.py Fri Nov 28 11:44:49 2003
@@ -0,0 +1,273 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Support for ZODB object serialization.
+
+ZODB serializes objects using a custom format based on Python pickles.
+When an object is unserialized, it can be loaded as either a ghost or
+a real object. A ghost is a persistent object of the appropriate type
+but without any state. The first time a ghost is accessed, the
+persistence machinery traps access and loads the actual state. A
+ghost allows many persistent objects to be loaded while minimizing the
+memory consumption of referenced but otherwise unused objects.
+
+Pickle format
+-------------
+
+ZODB stores serialized objects using a custom format based on pickle.
+Each serialized object has two parts: the class metadata and the
+object state. The class description must provide enough information
+to call the class's ``__new__`` and create an empty object. Once the
+object exists as a ghost, its state is passed to ``__setstate__``.
+
+The class metadata can be represented in two different ways, in order
+to provide backwards compatibility with many earlier versions of ZODB.
+The class metadata is always a two-tuple. The first element may also
+be a tuple, containing two string elements: name of a module and the
+name of a class. The second element of the class metadata tuple is a
+tuple of arguments to pass to the class's ``__new__``.
+
+Persistent references
+---------------------
+
+A persistent reference is a pair containing an oid and class metadata.
+When one persistent object pickle refers to another persistent object,
+the database uses a persistent reference. The format allows a
+significant optimization, because ghosts can be created directly from
+persistent references. If the reference was just an oid, a database
+access would be required to determine the class of the ghost.
+
+Because the persistent reference includes the class, it is not
+possible to change the class of a persistent object. If a transaction
+changed the class of an object, a new record with new class metadata
+would be written but all the old references would still include the
+old class.
+
+"""
+
+import cPickle
+import cStringIO
+
+from ZODB.coptimizations import new_persistent_id
+
+_marker = object()
+
+def myhasattr(obj, attr):
+ """Returns True or False or raises an exception."""
+ val = getattr(obj, attr, _marker)
+ return val is not _marker
+
+def getClassMetadata(obj):
+ klass = obj.__class__
+ if issubclass(klass, type):
+ # Handle ZClasses.
+ d = obj.__dict__.copy()
+ del d["_p_jar"]
+ args = obj.__name__, obj.__bases__, d
+ return klass, args
+ else:
+ getinitargs = getattr(klass, "__getinitargs__", None)
+ if getinitargs is None:
+ args = None
+ else:
+ args = getinitargs()
+ mod = getattr(klass, "__module__", None)
+ if mod is None:
+ return klass, args
+ else:
+ return (mod, klass.__name__), args
+
+class BaseObjectWriter:
+ """Serializes objects for storage in the database.
+
+ The ObjectWriter creates object pickles in the ZODB format. It
+ also detects new persistent objects reachable from the current
+ object.
+
+ The client is responsible for calling the close() method to avoid
+ leaking memory. The ObjectWriter uses a Pickler internally, and
+ Pickler objects do not participate in garbage collection. (Note
+ that in Python 2.3 and higher, the close() method would be
+ unnecessary because Picklers participate in garbage collection.)
+ """
+
+ def __init__(self, jar=None):
+ self._file = cStringIO.StringIO()
+ self._p = cPickle.Pickler(self._file, 1)
+ self._stack = []
+ self._p.persistent_id = new_persistent_id(jar, self._stack)
+ if jar is not None:
+ assert myhasattr(jar, "new_oid")
+ self._jar = jar
+
+ def serialize(self, obj):
+ return self._dump(getClassMetadata(obj), obj.__getstate__())
+
+ def _dump(self, classmeta, state):
+ # To reuse the existing cStringIO object, we must reset
+ # the file position to 0 and truncate the file after the
+ # new pickle is written.
+ self._file.seek(0)
+ self._p.clear_memo()
+ self._p.dump(classmeta)
+ self._p.dump(state)
+ self._file.truncate()
+ return self._file.getvalue()
+
+class ObjectWriter(BaseObjectWriter):
+
+ def __init__(self, obj):
+ BaseObjectWriter.__init__(self, obj._p_jar)
+ self._stack.append(obj)
+
+ def __iter__(self):
+ return NewObjectIterator(self._stack)
+
+class NewObjectIterator:
+
+ # The pickler is used as a forward iterator when the connection
+ # is looking for new objects to pickle.
+
+ def __init__(self, stack):
+ self._stack = stack
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ if self._stack:
+ elt = self._stack.pop()
+ return elt
+ else:
+ raise StopIteration
+
+class BaseObjectReader:
+
+ def _persistent_load(self, oid):
+ # subclasses must define _persistent_load().
+ raise NotImplementedError
+
+ def _get_class(self, module, name):
+ # subclasses must define _get_class()
+ raise NotImplementedError
+
+ def _get_unpickler(self, pickle):
+ file = cStringIO.StringIO(pickle)
+ unpickler = cPickle.Unpickler(file)
+ unpickler.persistent_load = self._persistent_load
+ return unpickler
+
+ def _new_object(self, klass, args):
+ if not args and not myhasattr(klass, "__getinitargs__"):
+ obj = klass.__new__(klass)
+ else:
+ obj = klass(*args)
+ if not isinstance(klass, type):
+ obj.__dict__.clear()
+
+ return obj
+
+ def getClassName(self, pickle):
+ unpickler = self._get_unpickler(pickle)
+ klass, newargs = unpickler.load()
+ if isinstance(klass, tuple):
+ return "%s.%s" % klass
+ else:
+ return klass.__name__
+
+ def getGhost(self, pickle):
+ unpickler = self._get_unpickler(pickle)
+ klass, args = unpickler.load()
+ if isinstance(klass, tuple):
+ klass = self._get_class(*klass)
+
+ return self._new_object(klass, args)
+
+ def getState(self, pickle):
+ unpickler = self._get_unpickler(pickle)
+ unpickler.load() # skip the class metadata
+ return unpickler.load()
+
+ def setGhostState(self, obj, pickle):
+ state = self.getState(pickle)
+ obj.__setstate__(state)
+
+ def getObject(self, pickle):
+ unpickler = self._get_unpickler(pickle)
+ klass, args = unpickler.load()
+ obj = self._new_object(klass, args)
+ state = unpickler.load()
+ obj.__setstate__(state)
+ return obj
+
+class ExternalReference(object):
+ pass
+
+class SimpleObjectReader(BaseObjectReader):
+ """Can be used to inspect a single object pickle.
+
+ It returns an ExternalReference() object for other persistent
+ objects. It can't instantiate the object.
+ """
+
+ ext_ref = ExternalReference()
+
+ def _persistent_load(self, oid):
+ return self.ext_ref
+
+ def _get_class(self, module, name):
+ return None
+
+class ConnectionObjectReader(BaseObjectReader):
+
+ def __init__(self, conn, cache, factory):
+ self._conn = conn
+ self._cache = cache
+ self._factory = factory
+
+ def _get_class(self, module, name):
+ return self._factory(self._conn, module, name)
+
+ def _persistent_load(self, oid):
+ if isinstance(oid, tuple):
+ # Quick instance reference. We know all we need to know
+ # to create the instance w/o hitting the db, so go for it!
+ oid, klass_info = oid
+ obj = self._cache.get(oid, None) # XXX it's not a dict
+ if obj is not None:
+ return obj
+
+ klass = self._get_class(*klass_info)
+ # XXX Why doesn't this have args?
+ obj = self._new_object(klass, None)
+ # XXX This doesn't address the last fallback that used to
+ # exist:
+## # Eek, we couldn't get the class. Hm. Maybe there's
+## # more current data in the object's actual record!
+## return self._conn[oid]
+
+ # XXX should be done by connection
+ obj._p_oid = oid
+ obj._p_jar = self._conn
+ # When an object is created, it is put in the UPTODATE
+ # state. We must explicitly deactivate it to turn it into
+ # a ghost.
+ obj._p_changed = None
+
+ self._cache[oid] = obj
+ return obj
+
+ obj = self._cache.get(oid)
+ if obj is not None:
+ return obj
+ return self._conn[oid]
=== Zope/lib/python/ZODB/BaseStorage.py 1.36 => 1.37 ===
--- Zope/lib/python/ZODB/BaseStorage.py:1.36 Thu Oct 2 14:17:19 2003
+++ Zope/lib/python/ZODB/BaseStorage.py Fri Nov 28 11:44:49 2003
@@ -16,8 +16,13 @@
$Id$
"""
import cPickle
+import threading
import time
+import UndoLogCompatible
+import POSException
+from persistent.TimeStamp import TimeStamp
+
import ThreadLock
import zLOG
from ZODB import bpthread
@@ -38,12 +43,12 @@
"create storage %s" % self.__name__)
# Allocate locks:
- l=ThreadLock.allocate_lock()
- self._lock_acquire=l.acquire
- self._lock_release=l.release
- l=bpthread.allocate_lock()
- self._commit_lock_acquire=l.acquire
- self._commit_lock_release=l.release
+ l = threading.RLock()
+ self._lock_acquire = l.acquire
+ self._lock_release = l.release
+ l = threading.Lock()
+ self._commit_lock_acquire = l.acquire
+ self._commit_lock_release = l.release
t=time.time()
t=self._ts=apply(TimeStamp,(time.gmtime(t)[:5]+(t%60,)))
=== Zope/lib/python/ZODB/ConflictResolution.py 1.20 => 1.21 ===
--- Zope/lib/python/ZODB/ConflictResolution.py:1.20 Tue Nov 18 08:17:16 2003
+++ Zope/lib/python/ZODB/ConflictResolution.py Fri Nov 28 11:44:49 2003
@@ -89,14 +89,15 @@
file = StringIO(newpickle)
unpickler = Unpickler(file)
unpickler.persistent_load = prfactory.persistent_load
- class_tuple = unpickler.load()[0]
+ meta = unpickler.load()
+ class_tuple = meta[0]
if bad_class(class_tuple):
return None
newstate = unpickler.load()
klass = load_class(class_tuple)
if klass is None:
return None
- inst = klass.__basicnew__()
+ inst = klass.__new__(klass)
try:
resolve = inst._p_resolveConflict
@@ -112,7 +113,7 @@
file = StringIO()
pickler = Pickler(file,1)
pickler.persistent_id = persistent_id
- pickler.dump(class_tuple)
+ pickler.dump(meta)
pickler.dump(resolved)
return file.getvalue(1)
except ConflictError:
=== Zope/lib/python/ZODB/Connection.py 1.101 => 1.102 ===
--- Zope/lib/python/ZODB/Connection.py:1.101 Mon Nov 3 13:56:30 2003
+++ Zope/lib/python/ZODB/Connection.py Fri Nov 28 11:44:49 2003
@@ -15,22 +15,23 @@
$Id$"""
-from cPickleCache import PickleCache
-from POSException import ConflictError, ReadConflictError, TransactionError
-from ExtensionClass import Base
-import ExportImport, TmpStore
-from zLOG import LOG, ERROR, BLATHER, WARNING
-from coptimizations import new_persistent_id
-from ConflictResolution import ResolvedSerial
-from Transaction import Transaction, get_transaction
-from ZODB.utils import oid_repr
-
-from cPickle import Unpickler, Pickler
-from cStringIO import StringIO
import sys
import threading
from time import time
-from types import StringType, ClassType
+
+from persistent import PickleCache
+from zLOG import LOG, ERROR, BLATHER, WARNING
+
+from ZODB.ConflictResolution import ResolvedSerial
+from ZODB.coptimizations import new_persistent_id
+from ZODB.ExportImport import ExportImport
+from ZODB.POSException \
+ import ConflictError, ReadConflictError, TransactionError
+from ZODB.TmpStore import TmpStore
+from ZODB.Transaction import Transaction, get_transaction
+from ZODB.utils import oid_repr, z64
+from ZODB.serialize \
+ import ObjectWriter, getClassMetadata, ConnectionObjectReader
global_code_timestamp = 0
@@ -43,9 +44,7 @@
global global_code_timestamp
global_code_timestamp = time()
-ExtensionKlass = Base.__class__
-
-class Connection(ExportImport.ExportImport, object):
+class Connection(ExportImport, object):
"""Object managers for individual object space.
An object space is a version of collection of objects. In a
@@ -129,87 +128,21 @@
ver = ''
return '<Connection at %08x%s>' % (id(self), ver)
- def _breakcr(self):
- # Persistent objects and the cache don't participate in GC.
- # Explicitly remove references from the connection to its
- # cache and to the root object, because they refer back to the
- # connection.
- if self._cache is not None:
- self._cache.clear()
- self._incrgc = None
- self.cacheGC = None
-
- def __getitem__(self, oid, tt=type(())):
+ def __getitem__(self, oid):
obj = self._cache.get(oid, None)
if obj is not None:
return obj
- __traceback_info__ = (oid)
p, serial = self._storage.load(oid, self._version)
- __traceback_info__ = (oid, p)
- file=StringIO(p)
- unpickler=Unpickler(file)
- unpickler.persistent_load=self._persistent_load
-
- object = unpickler.load()
-
- klass, args = object
-
- if type(klass) is tt:
- module, name = klass
- klass=self._db._classFactory(self, module, name)
-
- if (args is None or
- not args and not hasattr(klass,'__getinitargs__')):
- object=klass.__basicnew__()
- else:
- object = klass(*args)
- if klass is not ExtensionKlass:
- object.__dict__.clear()
-
- object._p_oid=oid
- object._p_jar=self
- object._p_changed=None
- object._p_serial=serial
-
- self._cache[oid] = object
- return object
-
- def _persistent_load(self,oid,
- tt=type(())):
-
- __traceback_info__=oid
-
- if type(oid) is tt:
- # Quick instance reference. We know all we need to know
- # to create the instance wo hitting the db, so go for it!
- oid, klass = oid
- obj = self._cache.get(oid, None)
- if obj is not None:
- return obj
-
- if type(klass) is tt:
- module, name = klass
- try: klass=self._db._classFactory(self, module, name)
- except:
- # Eek, we couldn't get the class. Hm.
- # Maybe their's more current data in the
- # object's actual record!
- return self[oid]
-
- object=klass.__basicnew__()
- object._p_oid=oid
- object._p_jar=self
- object._p_changed=None
+ obj = self._reader.getGhost(p)
- self._cache[oid] = object
+ obj._p_oid = oid
+ obj._p_jar = self
+ obj._p_changed = None
+ obj._p_serial = serial
- return object
-
- obj = self._cache.get(oid, None)
- if obj is not None:
- return obj
- return self[oid]
+ self._cache[oid] = obj
+ return obj
def sortKey(self):
# XXX will raise an exception if the DB hasn't been set
@@ -224,28 +157,27 @@
Any objects modified since the last transaction are invalidated.
"""
- self._db=odb
- self._storage=s=odb._storage
+ self._db = odb
+ self._reader = ConnectionObjectReader(self, self._cache,
+ self._db._classFactory)
+ self._storage = odb._storage
self._sortKey = odb._storage.sortKey
- self.new_oid=s.new_oid
+ self.new_oid = odb._storage.new_oid
if self._code_timestamp != global_code_timestamp:
# New code is in place. Start a new cache.
self._resetCache()
else:
self._flush_invalidations()
- self._opened=time()
+ self._opened = time()
return self
def _resetCache(self):
- '''
- Creates a new cache, discarding the old.
- '''
+ """Creates a new cache, discarding the old."""
self._code_timestamp = global_code_timestamp
self._invalidated.clear()
- orig_cache = self._cache
- orig_cache.clear()
- self._cache = cache = PickleCache(self, orig_cache.cache_size)
+ cache_size = self._cache.cache_size
+ self._cache = cache = PickleCache(self, cache_size)
self._incrgc = self.cacheGC = cache.incrgc
def abort(self, object, transaction):
@@ -331,100 +263,31 @@
# Nothing to do
return
- stack = [object]
-
- # Create a special persistent_id that passes T and the subobject
- # stack along:
- #
- # def persistent_id(object,
- # self=self,
- # stackup=stackup, new_oid=self.new_oid):
- # if (not hasattr(object, '_p_oid') or
- # type(object) is ClassType): return None
- #
- # oid=object._p_oid
- #
- # if oid is None or object._p_jar is not self:
- # oid = self.new_oid()
- # object._p_jar=self
- # object._p_oid=oid
- # stackup(object)
- #
- # klass=object.__class__
- #
- # if klass is ExtensionKlass: return oid
- #
- # if hasattr(klass, '__getinitargs__'): return oid
- #
- # module=getattr(klass,'__module__','')
- # if module: klass=module, klass.__name__
- #
- # return oid, klass
-
- file=StringIO()
- seek=file.seek
- pickler=Pickler(file,1)
- pickler.persistent_id=new_persistent_id(self, stack)
- dbstore=self._storage.store
- file=file.getvalue
- cache=self._cache
- get=cache.get
- dump=pickler.dump
- clear_memo=pickler.clear_memo
-
-
- version=self._version
-
- while stack:
- object=stack[-1]
- del stack[-1]
- oid=object._p_oid
- serial=getattr(object, '_p_serial', '\0\0\0\0\0\0\0\0')
- if serial == '\0\0\0\0\0\0\0\0':
+ w = ObjectWriter(object)
+ for obj in w:
+ oid = obj._p_oid
+ serial = getattr(obj, '_p_serial', z64)
+ if serial == z64:
# new object
self._creating.append(oid)
else:
#XXX We should never get here
if invalid(oid) and not hasattr(object, '_p_resolveConflict'):
- raise ConflictError(object=object)
+ raise ConflictError(object=obj)
self._modified.append(oid)
- klass = object.__class__
-
- if klass is ExtensionKlass:
- # Yee Ha!
- dict={}
- dict.update(object.__dict__)
- del dict['_p_jar']
- args=object.__name__, object.__bases__, dict
- state=None
- else:
- if hasattr(klass, '__getinitargs__'):
- args = object.__getinitargs__()
- len(args) # XXX Assert it's a sequence
- else:
- args = None # New no-constructor protocol!
-
- module=getattr(klass,'__module__','')
- if module: klass=module, klass.__name__
- __traceback_info__=klass, oid, self._version
- state=object.__getstate__()
-
- seek(0)
- clear_memo()
- dump((klass,args))
- dump(state)
- p=file(1)
- s=dbstore(oid,serial,p,version,transaction)
+ p = w.serialize(obj)
+ s = self._storage.store(oid, serial, p, self._version, transaction)
self._store_count = self._store_count + 1
# Put the object in the cache before handling the
# response, just in case the response contains the
# serial number for a newly created object
- try: cache[oid]=object
+ try:
+ self._cache[oid] = obj
except:
# Dang, I bet its wrapped:
- if hasattr(object, 'aq_base'):
- cache[oid]=object.aq_base
+ if hasattr(obj, 'aq_base'):
+ self._cache[oid] = obj.aq_base
else:
raise
@@ -447,7 +310,6 @@
load=src.load
store=tmp.store
dest=self._version
- get=self._cache.get
oids=src._index.keys()
# Copy invalidating and creating info from temporary storage:
@@ -488,11 +350,11 @@
del o._p_jar
del o._p_oid
- #XXX
-
- def db(self): return self._db
+ def db(self):
+ return self._db
- def getVersion(self): return self._version
+ def getVersion(self):
+ return self._version
def isReadOnly(self):
return self._storage.isReadOnly()
@@ -537,7 +399,7 @@
self.getTransaction().register(object)
def root(self):
- return self['\0\0\0\0\0\0\0\0']
+ return self[z64]
def setstate(self, obj):
oid = obj._p_oid
@@ -559,7 +421,7 @@
p, serial = self._storage.load(oid, self._version)
self._load_count = self._load_count + 1
invalid = self._is_invalidated(obj)
- self._set_ghost_state(obj, p)
+ self._reader.setGhostState(obj, p)
obj._p_serial = serial
if invalid:
self._handle_independent(obj)
@@ -593,19 +455,6 @@
finally:
self._inv_lock.release()
- def _set_ghost_state(self, obj, p):
- file = StringIO(p)
- unpickler = Unpickler(file)
- unpickler.persistent_load = self._persistent_load
- unpickler.load()
- state = unpickler.load()
-
- setstate = getattr(obj, "__setstate__", None)
- if setstate is None:
- obj.update(state)
- else:
- setstate(state)
-
def _handle_independent(self, obj):
# Helper method for setstate() handles possibly independent objects
# Call _p_independent(), if it returns True, setstate() wins.
@@ -624,42 +473,27 @@
self.getTransaction().register(obj)
raise ReadConflictError(object=obj)
- def oldstate(self, object, serial):
- oid=object._p_oid
- p = self._storage.loadSerial(oid, serial)
- file=StringIO(p)
- unpickler=Unpickler(file)
- unpickler.persistent_load=self._persistent_load
- unpickler.load()
- return unpickler.load()
-
- def setklassstate(self, object):
+ def oldstate(self, obj, serial):
+ p = self._storage.loadSerial(obj._p_oid, serial)
+ return self._reader.getState(p)
+
+ def setklassstate(self, obj):
+ # Special case code to handle ZClasses, I think.
+ # Called the cache when an object of type type is invalidated.
try:
- oid=object._p_oid
- __traceback_info__=oid
+ oid = obj._p_oid
p, serial = self._storage.load(oid, self._version)
- file=StringIO(p)
- unpickler=Unpickler(file)
- unpickler.persistent_load=self._persistent_load
-
- copy = unpickler.load()
-
- klass, args = copy
-
- if klass is not ExtensionKlass:
- LOG('ZODB',ERROR,
- "Unexpected klass when setting class state on %s"
- % getattr(object,'__name__','(?)'))
- return
-
- copy = klass(*args)
- object.__dict__.clear()
- object.__dict__.update(copy.__dict__)
-
- object._p_oid=oid
- object._p_jar=self
- object._p_changed=0
- object._p_serial=serial
+
+ # We call getGhost(), but we actually get a non-ghost back.
+ # The object is a class, which can't actually be ghosted.
+ copy = self._reader.getGhost(p)
+ obj.__dict__.clear()
+ obj.__dict__.update(copy.__dict__)
+
+ obj._p_oid = oid
+ obj._p_jar = self
+ obj._p_changed = 0
+ obj._p_serial = serial
except:
LOG('ZODB',ERROR, 'setklassstate failed', error=sys.exc_info())
raise
@@ -679,7 +513,7 @@
if sub:
# Sub-transaction!
if self._tmp is None:
- _tmp = TmpStore.TmpStore(self._version)
+ _tmp = TmpStore(self._version)
self._tmp = self._storage
self._storage = _tmp
_tmp.registerDB(self._db, 0)
@@ -718,7 +552,7 @@
if not store_return:
return
- if isinstance(store_return, StringType):
+ if isinstance(store_return, str):
assert oid is not None
self._handle_one_serial(oid, store_return, change)
else:
@@ -726,7 +560,7 @@
self._handle_one_serial(oid, serial, change)
def _handle_one_serial(self, oid, serial, change):
- if not isinstance(serial, StringType):
+ if not isinstance(serial, str):
raise serial
obj = self._cache.get(oid, None)
if obj is None:
@@ -795,8 +629,3 @@
new._p_changed=1
self.getTransaction().register(new)
self._cache[oid]=new
-
-class tConnection(Connection):
-
- def close(self):
- self._breakcr()
=== Zope/lib/python/ZODB/DB.py 1.56 => 1.57 ===
--- Zope/lib/python/ZODB/DB.py:1.56 Tue Nov 18 08:17:16 2003
+++ Zope/lib/python/ZODB/DB.py Fri Nov 28 11:44:49 2003
@@ -84,8 +84,8 @@
storage.load('\0\0\0\0\0\0\0\0','')
except KeyError:
# Create the database's root in the storage if it doesn't exist
- import PersistentMapping
- root = PersistentMapping.PersistentMapping()
+ from persistent.mapping import PersistentMapping
+ root = PersistentMapping()
# Manually create a pickle for the root to put in the storage.
# The pickle must be in the special ZODB format.
file = cStringIO.StringIO()
@@ -267,9 +267,6 @@
def close(self):
self._storage.close()
- for x, allocated in self._pools[1]:
- for c in allocated:
- c._breakcr()
def commitVersion(self, source, destination='', transaction=None):
if transaction is None:
=== Zope/lib/python/ZODB/DemoStorage.py 1.21 => 1.22 ===
--- Zope/lib/python/ZODB/DemoStorage.py:1.21 Thu Oct 2 14:17:19 2003
+++ Zope/lib/python/ZODB/DemoStorage.py Fri Nov 28 11:44:49 2003
@@ -83,7 +83,7 @@
import base64, time, string
from ZODB import POSException, BaseStorage, utils
-from TimeStamp import TimeStamp
+from persistent.TimeStamp import TimeStamp
from cPickle import loads
from BTrees import OOBTree
@@ -164,12 +164,13 @@
self._lock_acquire()
try:
- v=self._vindex.get(src, None)
- if v is None: return
+ v = self._vindex.get(src)
+ if v is None:
+ return
newserial = self._serial
- tindex=self._tindex
- oids=[]
+ tindex = self._tindex
+ oids = []
for r in v.values():
oid, serial, pre, vdata, p = r
assert vdata is not None
@@ -180,10 +181,10 @@
new_vdata = None
tindex.append([oid, newserial, r, new_vdata, p])
-
return oids
- finally: self._lock_release()
+ finally:
+ self._lock_release()
def load(self, oid, version):
self._lock_acquire()
@@ -249,7 +250,8 @@
nv=old
if serial != oserial:
- raise POSException.ConflictError(serials=(oserial, serial))
+ raise POSException.ConflictError(
+ oid=oid, serials=(oserial, serial), data=data)
serial=self._serial
r=[oid, serial, old, version and (version, nv) or None, data]
=== Zope/lib/python/ZODB/ExportImport.py 1.17 => 1.18 ===
--- Zope/lib/python/ZODB/ExportImport.py:1.17 Thu Oct 2 19:58:01 2003
+++ Zope/lib/python/ZODB/ExportImport.py Fri Nov 28 11:44:49 2003
@@ -60,15 +60,11 @@
def importFile(self, file, clue='', customImporters=None):
# This is tricky, because we need to work in a transaction!
- if type(file) is StringType:
- file_name=file
- file=open(file,'rb')
- else:
- try: file_name=file.name
- except: file_name='(unknown)'
- read=file.read
+ if isinstance(file, StringType):
+ file = open(file,'rb')
+ read = file.read
- magic=read(4)
+ magic = read(4)
if magic != 'ZEXP':
if customImporters and customImporters.has_key(magic):
@@ -77,7 +73,8 @@
raise POSException.ExportError, 'Invalid export header'
t = self.getTransaction()
- if clue: t.note(clue)
+ if clue:
+ t.note(clue)
return_oid_list = []
self.onCommitAction('_importDuringCommit', file, return_oid_list)
@@ -151,7 +148,6 @@
pickler.dump(unpickler.load())
pickler.dump(unpickler.load())
p=newp.getvalue()
- plen=len(p)
store(oid, None, p, version, transaction)
=== Zope/lib/python/ZODB/FileStorage.py 1.139 => 1.140 ===
--- Zope/lib/python/ZODB/FileStorage.py:1.139 Thu Oct 2 18:14:04 2003
+++ Zope/lib/python/ZODB/FileStorage.py Fri Nov 28 11:44:49 2003
@@ -130,9 +130,9 @@
# Not all platforms have fsync
fsync = getattr(os, "fsync", None)
+from persistent.TimeStamp import TimeStamp
from ZODB import BaseStorage, ConflictResolution, POSException
from ZODB.POSException import UndoError, POSKeyError, MultipleUndoErrors
-from ZODB.TimeStamp import TimeStamp
from ZODB.lock_file import LockFile
from ZODB.utils import p64, u64, cp, z64
from ZODB.fspack import FileStoragePacker
@@ -773,11 +773,13 @@
oserial = cached_serial
if serial != oserial:
- data = self.tryToResolveConflict(oid, oserial, serial,
+ rdata = self.tryToResolveConflict(oid, oserial, serial,
data)
- if data is None:
- raise POSException.ConflictError(oid=oid,
- serials=(oserial, serial))
+ if rdata is None:
+ raise POSException.ConflictError(
+ oid=oid, serials=(oserial, serial), data=data)
+ else:
+ data = rdata
else:
oserial=serial
@@ -2227,7 +2229,6 @@
self._file.seek(pos)
h = self._file.read(DATA_HDR_LEN)
oid, serial, sprev, stloc, vlen, splen = unpack(DATA_HDR, h)
- prev = u64(sprev)
tloc = u64(stloc)
plen = u64(splen)
dlen = DATA_HDR_LEN + (plen or 8)
@@ -2235,7 +2236,6 @@
if vlen:
dlen += (16 + vlen)
tmp = self._file.read(16)
- pv = u64(tmp[8:16])
version = self._file.read(vlen)
else:
version = ''
=== Zope/lib/python/ZODB/MappingStorage.py 1.9 => 1.10 ===
--- Zope/lib/python/ZODB/MappingStorage.py:1.9 Mon Jan 13 19:12:14 2003
+++ Zope/lib/python/ZODB/MappingStorage.py Fri Nov 28 11:44:49 2003
@@ -26,7 +26,7 @@
from ZODB import utils
from ZODB import BaseStorage
from ZODB import POSException
-from ZODB.TimeStamp import TimeStamp
+from persistent.TimeStamp import TimeStamp
class MappingStorage(BaseStorage.BaseStorage):
@@ -71,7 +71,9 @@
old = self._index[oid]
oserial = old[:8]
if serial != oserial:
- raise POSException.ConflictError(serials=(oserial, serial))
+ raise POSException.ConflictError(oid=oid,
+ serials=(oserial, serial),
+ data=data)
serial = self._serial
self._tindex.append((oid, serial+data))
=== Zope/lib/python/ZODB/Mount.py 1.20 => 1.21 ===
--- Zope/lib/python/ZODB/Mount.py:1.20 Tue Nov 18 08:17:16 2003
+++ Zope/lib/python/ZODB/Mount.py Fri Nov 28 11:44:49 2003
@@ -16,9 +16,9 @@
$Id$"""
__version__='$Revision$'[11:-2]
-import thread, Persistence, Acquisition
+import thread, persistent, Acquisition
from Acquisition import aq_base
-import ExtensionClass, string, time, sys
+import string, time, sys
from POSException import MountedStorageError
from zLOG import LOG, ERROR, INFO, WARNING
@@ -44,7 +44,7 @@
return parent_db._classFactory(parent_conn, module, name)
-class MountPoint(Persistence.Persistent, Acquisition.Implicit):
+class MountPoint(persistent.Persistent, Acquisition.Implicit):
'''The base class for a Zope object which, when traversed,
accesses a different database.
'''
=== Zope/lib/python/ZODB/POSException.py 1.21 => 1.22 ===
--- Zope/lib/python/ZODB/POSException.py:1.21 Thu Oct 2 14:17:19 2003
+++ Zope/lib/python/ZODB/POSException.py Fri Nov 28 11:44:49 2003
@@ -51,13 +51,17 @@
related to conflict. The first is the revision of object that
is in conflict, the second is the revision of that the current
transaction read when it started.
+ data : string
+ The database record that failed to commit, used to put the
+ class name in the error message.
The caller should pass either object or oid as a keyword argument,
but not both of them. If object is passed, it should be a
persistent object with an _p_oid attribute.
"""
- def __init__(self, message=None, object=None, oid=None, serials=None):
+ def __init__(self, message=None, object=None, oid=None, serials=None,
+ data=None):
if message is None:
self.message = "database conflict error"
else:
@@ -75,6 +79,14 @@
assert self.oid is None
self.oid = oid
+ if data is not None:
+ # avoid circular import chain
+ from ZODB.serialize import SimpleObjectReader
+ self.class_name = SimpleObjectReader().getClassName(data)
+## else:
+## if message != "data read conflict error":
+## raise RuntimeError
+
self.serials = serials
def __str__(self):
@@ -119,13 +131,66 @@
serials=serials)
class BTreesConflictError(ConflictError):
- """A special subclass for BTrees conflict errors.
+ """A special subclass for BTrees conflict errors."""
- These return an undocumented four-tuple.
- """
- def __init__(self, *btree_args):
- ConflictError.__init__(self, message="BTrees conflict error")
- self.btree = btree_args
+ msgs = [# 0; i2 or i3 bucket split; positions are all -1
+ 'Conflicting bucket split',
+
+ # 1; keys the same, but i2 and i3 values differ, and both values
+ # differ from i1's value
+ 'Conflicting changes',
+
+ # 2; i1's value changed in i2, but key+value deleted in i3
+ 'Conflicting delete and change',
+
+ # 3; i1's value changed in i3, but key+value deleted in i2
+ 'Conflicting delete and change',
+
+ # 4; i1 and i2 both added the same key, or both deleted the
+ # same key
+ 'Conflicting inserts or deletes',
+
+ # 5; i2 and i3 both deleted the same key
+ 'Conflicting deletes',
+
+ # 6; i2 and i3 both added the same key
+ 'Conflicting inserts',
+
+ # 7; i2 and i3 both deleted the same key, or i2 changed the value
+ # associated with a key and i3 deleted that key
+ 'Conflicting deletes, or delete and change',
+
+ # 8; i2 and i3 both deleted the same key, or i3 changed the value
+ # associated with a key and i2 deleted that key
+ 'Conflicting deletes, or delete and change',
+
+ # 9; i2 and i3 both deleted the same key
+ 'Conflicting deletes',
+
+ # 10; i2 and i3 deleted all the keys, and didn't insert any,
+ # leaving an empty bucket; conflict resolution doesn't have
+ # enough info to unlink an empty bucket from its containing
+ # BTree correctly
+ 'Empty bucket from deleting all keys',
+
+ # 11; conflicting changes in an internal BTree node
+ 'Conflicting changes in an internal BTree node',
+ ]
+
+ def __init__(self, p1, p2, p3, reason):
+ self.p1 = p1
+ self.p2 = p2
+ self.p3 = p3
+ self.reason = reason
+
+ def __repr__(self):
+ return "BTreesConflictError(%d, %d, %d, %d)" % (self.p1,
+ self.p2,
+ self.p3,
+ self.reason)
+ def __str__(self):
+ return "BTrees conflict error at %d/%d/%d: %s" % (
+ self.p1, self.p2, self.p3, self.msgs[self.reason])
class DanglingReferenceError(TransactionError):
"""An object has a persistent reference to a missing object.
=== Zope/lib/python/ZODB/Transaction.py 1.54 => 1.55 ===
--- Zope/lib/python/ZODB/Transaction.py:1.54 Sun Oct 5 10:25:11 2003
+++ Zope/lib/python/ZODB/Transaction.py Fri Nov 28 11:44:49 2003
@@ -251,23 +251,27 @@
else:
self._finish_many(jars)
except:
- # Ugh, we got an got an error during commit, so we
- # have to clean up. First save the original exception
- # in case the cleanup process causes another
- # exception.
- error = sys.exc_info()
- try:
- self._commit_error(objects, ncommitted, jars, subjars)
- except:
- LOG('ZODB', ERROR,
- "A storage error occured during transaction "
- "abort. This shouldn't happen.",
- error=sys.exc_info())
- raise error[0], error[1], error[2]
+ self._cleanup(objects, ncommitted, jars, subjars)
finally:
del objects[:] # clear registered
if not subtransaction and self._id is not None:
free_transaction()
+
+ def _cleanup(self, objects, ncommitted, jars, subjars):
+ # Ugh, we got an got an error during commit, so we
+ # have to clean up. First save the original exception
+ # in case the cleanup process causes another
+ # exception.
+ error = sys.exc_info()
+ try:
+ self._commit_error(objects, ncommitted, jars, subjars)
+ except:
+ LOG("ZODB", ERROR,
+ "A storage error occured during transaction "
+ "abort. This shouldn't happen.",
+ error=sys.exc_info())
+ raise error[0], error[1], error[2]
+
def _get_jars(self, objects, subtransaction):
# Returns a list of jars for this transaction.
=== Zope/lib/python/ZODB/__init__.py 1.25 => 1.26 ===
--- Zope/lib/python/ZODB/__init__.py:1.25 Wed Oct 8 11:02:45 2003
+++ Zope/lib/python/ZODB/__init__.py Fri Nov 28 11:44:49 2003
@@ -12,36 +12,14 @@
#
##############################################################################
-__version__ = '3.3a0'
+__version__ = "3.3a1"
import sys
-import cPersistence, Persistence
-from zLOG import register_subsystem
-
-# This is lame. Don't look. :(
-sys.modules['cPersistence'] = cPersistence
-
-Persistent = cPersistence.Persistent
-
-# Install Persistent and PersistentMapping in Persistence
-if not hasattr(Persistence, 'Persistent'):
- Persistence.Persistent = Persistent
- Persistent.__module__ = 'Persistence'
- Persistence.Overridable = cPersistence.Overridable
- Persistence.Overridable.__module__ = 'Persistence'
- if not hasattr(Persistence, 'PersistentMapping'):
- import PersistentMapping
- sys.modules['PersistentMapping'] = PersistentMapping
- sys.modules['BoboPOS'] = sys.modules['ZODB']
- sys.modules['BoboPOS.PersistentMapping'] = PersistentMapping
- PersistentMapping = PersistentMapping.PersistentMapping
- from PersistentMapping import PersistentMapping
- Persistence.PersistentMapping = PersistentMapping
- PersistentMapping.__module__ = 'Persistence'
- del PersistentMapping
-
-del cPersistence
+from persistent import TimeStamp
from DB import DB
-
import Transaction
+
+# Backward compat for old imports. I don't think TimeStamp should
+# really be in persistent anyway
+sys.modules['ZODB.TimeStamp'] = sys.modules['persistent.TimeStamp']
=== Zope/lib/python/ZODB/conversionhack.py 1.4 => 1.5 ===
--- Zope/lib/python/ZODB/conversionhack.py:1.4 Wed Aug 14 18:07:09 2002
+++ Zope/lib/python/ZODB/conversionhack.py Fri Nov 28 11:44:49 2003
@@ -12,7 +12,7 @@
#
##############################################################################
-import PersistentMapping
+import persistent.mapping
class fixer:
def __of__(self, parent):
@@ -27,7 +27,7 @@
hack=hack()
def __basicnew__():
- r=PersistentMapping.PersistentMapping()
+ r=persistent.mapping.PersistentMapping()
r.__setstate__=fixer
return r
=== Zope/lib/python/ZODB/coptimizations.c 1.23 => 1.24 ===
--- Zope/lib/python/ZODB/coptimizations.c:1.23 Fri Dec 13 16:56:05 2002
+++ Zope/lib/python/ZODB/coptimizations.c Fri Nov 28 11:44:49 2003
@@ -16,24 +16,16 @@
"\n"
"$Id$\n";
-#include "Python.h"
-#define DONT_USE_CPERSISTENCECAPI
#include "cPersistence.h"
-static void PyVar_Assign(PyObject **v, PyObject *e) { Py_XDECREF(*v); *v=e;}
-#define ASSIGN(V,E) PyVar_Assign(&(V),(E))
-#define UNLESS(E) if(!(E))
-#define UNLESS_ASSIGN(V,E) ASSIGN(V,E); UNLESS(V)
-#define OBJECT(O) ((PyObject*)(O))
-
static PyObject *py__p_oid, *py__p_jar, *py___getinitargs__, *py___module__;
static PyObject *py_new_oid, *py___class__, *py___name__;
static PyObject *InvalidObjectReference;
typedef struct {
- PyObject_HEAD
- PyObject *jar, *stack, *new_oid;
+ PyObject_HEAD
+ PyObject *jar, *stack, *new_oid;
} persistent_id;
static PyTypeObject persistent_idType;
@@ -74,25 +66,15 @@
{
PyObject *class = NULL;
- if (!PyExtensionClass_Check(object)) {
- if (PyExtensionInstance_Check(object)) {
- class = PyObject_GetAttr(object, py___class__);
- if (!class) {
- PyErr_Clear();
- return 0;
- }
- /* The __class__ must be an extension class. */
- if (!(((PyExtensionClass*)class)->class_flags
- & PERSISTENT_TYPE_FLAG)) {
- Py_DECREF(class);
- return 0;
- }
- }
- else
- /* Most objects will exit via this path. They are neither
- extension classes nor instances of them.
- */
+ if (!PyType_Check(object)) {
+ if (!PER_TypeCheck(object))
+ return 0;
+
+ class = PyObject_GetAttr(object, py___class__);
+ if (!class) {
+ PyErr_Clear();
return 0;
+ }
}
*out_class = class;
return 1;
@@ -217,8 +199,7 @@
goto err;
}
- if (PyExtensionClass_Check(object)
- || PyObject_HasAttr(klass, py___getinitargs__))
+ if (PyType_Check(object) || PyObject_HasAttr(klass, py___getinitargs__))
goto return_oid;
t2 = get_class_tuple(klass, oid);
@@ -257,29 +238,28 @@
static PyTypeObject persistent_idType = {
PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
+ 0, /*ob_size*/
"persistent_id", /*tp_name*/
sizeof(persistent_id), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- /* methods */
+ 0, /*tp_itemsize*/
(destructor)persistent_id_dealloc, /*tp_dealloc*/
- (printfunc)0, /*tp_print*/
- (getattrfunc)0, /*obsolete tp_getattr*/
- (setattrfunc)0, /*obsolete tp_setattr*/
- (cmpfunc)0, /*tp_compare*/
- (reprfunc)0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- (hashfunc)0, /*tp_hash*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
(ternaryfunc)persistent_id_call, /*tp_call*/
- (reprfunc)0, /*tp_str*/
- (getattrofunc)0, /*tp_getattro*/
- (setattrofunc)0, /*tp_setattro*/
-
- /* Space for future expansion */
- 0L,0L,
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
"C implementation of the persistent_id function defined in Connection.py"
+ /* tp_doc */
};
/* End of code for persistent_id objects */
@@ -297,7 +277,7 @@
void
initcoptimizations(void)
{
- PyObject *m, *d;
+ PyObject *m;
#define make_string(S) if (! (py_ ## S=PyString_FromString(#S))) return
make_string(_p_oid);
@@ -309,20 +289,23 @@
make_string(new_oid);
/* Get InvalidObjectReference error */
- UNLESS (m=PyString_FromString("ZODB.POSException")) return;
- ASSIGN(m, PyImport_Import(m));
- UNLESS (m) return;
- ASSIGN(m, PyObject_GetAttrString(m, "InvalidObjectReference"));
- UNLESS (m) return;
- InvalidObjectReference=m;
+ m = PyImport_ImportModule("ZODB.POSException");
+ if (!m)
+ return;
+ InvalidObjectReference = PyObject_GetAttrString(m,
+ "InvalidObjectReference");
+ Py_DECREF(m);
+ if (!InvalidObjectReference)
+ return;
- if (!ExtensionClassImported)
+ cPersistenceCAPI = PyCObject_Import("persistent.cPersistence", "CAPI");
+ if (!cPersistenceCAPI)
return;
m = Py_InitModule3("coptimizations", Module_Level__methods,
coptimizations_doc_string);
- d = PyModule_GetDict(m);
persistent_idType.ob_type = &PyType_Type;
- PyDict_SetItemString(d,"persistent_idType", OBJECT(&persistent_idType));
+ Py_INCREF((PyObject *)&persistent_idType);
+ PyModule_AddObject(m, "persistent_idType", (PyObject *)&persistent_idType);
}
=== Zope/lib/python/ZODB/fsIndex.py 1.4 => 1.5 ===
--- Zope/lib/python/ZODB/fsIndex.py:1.4 Tue Dec 3 13:45:16 2002
+++ Zope/lib/python/ZODB/fsIndex.py Fri Nov 28 11:44:49 2003
@@ -8,12 +8,11 @@
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""Implement an OID to File-position (long integer) mapping
-"""
-#
+"""Implement an OID to File-position (long integer) mapping."""
+
# To save space, we do two things:
#
# 1. We split the keys (OIDS) into 6-byte prefixes and 2-byte suffixes.
@@ -29,29 +28,26 @@
# suffix to 6-byte data. This should reduce the overall memory usage to
# 8-16 bytes per OID.
#
+# Since the mapping from suffix to data contains at most 256 entries,
+# we use a BTree bucket instead of a full BTree to store the results.
+#
# We use p64 to convert integers to 8-byte strings and lop off the two
# high-order bytes when saving. On loading data, we add the leading
-# bytes back before using U64 to convert the data back to (long)
+# bytes back before using u64 to convert the data back to (long)
# integers.
-from BTrees._fsBTree import fsBTree as _fsBTree
-
+from __future__ import generators
import struct
-# convert between numbers and six-byte strings
+from BTrees._fsBTree import fsBucket
-_t32 = 1L<< 32
+# convert between numbers and six-byte strings
def num2str(n):
- h, l = divmod(long(n), _t32)
- return struct.pack(">HI", h, l)
+ return struct.pack(">Q", n)[2:]
def str2num(s):
- h, l = struct.unpack(">HI", s)
- if h:
- return (long(h) << 32) + l
- else:
- return l
+ return struct.unpack(">Q", "\000\000" + s)[0]
class fsIndex:
@@ -75,7 +71,7 @@
treekey = key[:6]
tree = self._data.get(treekey)
if tree is None:
- tree = _fsBTree()
+ tree = fsBucket()
self._data[treekey] = tree
tree[key[6:]] = value
@@ -96,14 +92,19 @@
def __contains__(self, key):
tree = self._data.get(key[:6])
if tree is None:
- return 0
+ return False
v = tree.get(key[6:], None)
if v is None:
- return 0
- return 1
+ return False
+ return True
def clear(self):
self._data.clear()
+
+ def __iter__(self):
+ for prefix, tree in self._data.items():
+ for suffix in tree:
+ yield prefix + suffix
def keys(self):
r = []
=== Zope/lib/python/ZODB/fsdump.py 1.13 => 1.14 ===
--- Zope/lib/python/ZODB/fsdump.py:1.13 Wed Nov 12 00:00:43 2003
+++ Zope/lib/python/ZODB/fsdump.py Fri Nov 28 11:44:49 2003
@@ -25,9 +25,9 @@
from ZODB.FileStorage import TRANS_HDR, TRANS_HDR_LEN
from ZODB.FileStorage import DATA_HDR, DATA_HDR_LEN, DATA_VERSION_HDR_LEN
from ZODB.FileStorage import FileIterator
-from ZODB.TimeStamp import TimeStamp
from ZODB.utils import u64
from ZODB.tests.StorageTestBase import zodb_unpickle
+from persistent.TimeStamp import TimeStamp
from cPickle import Unpickler
from cStringIO import StringIO
=== Zope/lib/python/ZODB/fspack.py 1.13 => 1.14 ===
--- Zope/lib/python/ZODB/fspack.py:1.13 Thu Oct 2 20:33:06 2003
+++ Zope/lib/python/ZODB/fspack.py Fri Nov 28 11:44:49 2003
@@ -177,7 +177,6 @@
"txnlen (%d) < headerlen(%d)", th.tlen, th.headerlen())
def checkData(self, th, tpos, dh, pos):
- tend = tpos + th.tlen
if dh.tloc != tpos:
self.fail(pos, "data record does not point to transaction header"
": %d != %d", dh.tloc, tpos)
@@ -345,7 +344,6 @@
if not prev:
return None
- pnv = None
h = self._read_data_header(prev, oid)
# If the previous record is for a version, it must have
# a valid pnv.
@@ -712,7 +710,6 @@
return pos
def copyToPacktime(self):
- offset = 0L # the amount of space freed by packing
pos = self._metadata_size
new_pos = pos
@@ -778,7 +775,6 @@
s = th.asString()
new_tpos = self._tfile.tell()
self._tfile.write(s)
- new_pos = new_tpos + len(s)
copy = 1
if h.plen:
@@ -790,7 +786,6 @@
data = self.fetchBackpointer(h.oid, h.back)
self.writePackedDataRecord(h, data, new_tpos)
- new_pos = self._tfile.tell()
return new_tpos, pos
=== Zope/lib/python/ZODB/fsrecover.py 1.13 => 1.14 ===
--- Zope/lib/python/ZODB/fsrecover.py:1.13 Thu Oct 2 14:17:19 2003
+++ Zope/lib/python/ZODB/fsrecover.py Fri Nov 28 11:44:49 2003
@@ -83,7 +83,7 @@
import getopt, ZODB.FileStorage, struct, time
from struct import unpack
from ZODB.utils import t32, p64, u64
-from ZODB.TimeStamp import TimeStamp
+from persistent.TimeStamp import TimeStamp
from cPickle import loads
from ZODB.FileStorage import RecordIterator
@@ -323,8 +323,8 @@
l = len(r.data)
print "%7d %s %s" % (u64(r.oid), l, r.version)
- s = ofs.restore(r.oid, r.serial, r.data, r.version,
- r.data_txn, txn)
+ ofs.restore(r.oid, r.serial, r.data, r.version, r.data_txn,
+ txn)
nrec += 1
except (KeyboardInterrupt, SystemExit):
raise
=== Zope/lib/python/ZODB/fstools.py 1.1 => 1.2 ===
--- Zope/lib/python/ZODB/fstools.py:1.1 Mon Nov 18 15:45:48 2002
+++ Zope/lib/python/ZODB/fstools.py Fri Nov 28 11:44:49 2003
@@ -24,7 +24,7 @@
from ZODB.FileStorage import TRANS_HDR, DATA_HDR, TRANS_HDR_LEN, \
DATA_HDR_LEN, DATA_VERSION_HDR_LEN
from ZODB.utils import p64, u64
-from ZODB.TimeStamp import TimeStamp
+from persistent.TimeStamp import TimeStamp
class TxnHeader:
"""Object representing a transaction record header.
=== Zope/lib/python/ZODB/utils.py 1.18 => 1.19 ===
--- Zope/lib/python/ZODB/utils.py:1.18 Thu Oct 2 14:17:19 2003
+++ Zope/lib/python/ZODB/utils.py Fri Nov 28 11:44:49 2003
@@ -13,7 +13,8 @@
##############################################################################
import sys
-import TimeStamp, time
+import time
+from persistent.TimeStamp import TimeStamp
from struct import pack, unpack
from types import StringType
@@ -80,7 +81,7 @@
def newTimeStamp(old=None,
- TimeStamp=TimeStamp.TimeStamp,
+ TimeStamp=TimeStamp,
time=time.time, gmtime=time.gmtime):
t = time()
ts = TimeStamp(gmtime(t)[:5]+(t%60,))
=== Removed File Zope/lib/python/ZODB/PersistentList.py ===
=== Removed File Zope/lib/python/ZODB/PersistentMapping.py ===
=== Removed File Zope/lib/python/ZODB/cPersistence.c ===
=== Removed File Zope/lib/python/ZODB/cPersistence.h ===
More information about the Zope-Checkins
mailing list