[Zope-CVS] CVS: Products/AdaptableStorage/zodb - public.py:1.1 ASConnection.py:1.2 ASStorage.py:1.2
Shane Hathaway
shane@zope.com
Tue, 3 Dec 2002 18:10:56 -0500
Update of /cvs-repository/Products/AdaptableStorage/zodb
In directory cvs.zope.org:/tmp/cvs-serv22143/zodb
Modified Files:
ASConnection.py ASStorage.py
Added Files:
public.py
Log Message:
Running AdaptableStorage with the latest Zope revealed some flaws.
Fixed them all.
- Consistent ordering of transaction participants now makes it impossible to
add a jar to the transaction after the commit() method has begun.
AdaptableStorage (and perhaps other projects like ZPatterns) relied on
the ability to add a jar after commit has started. This could lead to
a deadlock. Reworked ASStorage, FSConnection, and the tests to deal with
this.
- Serials are now required to be hashable. This makes serials, used to
prevent conflicts, simpler and more robust.
- DBTab needs some kind of class it can call directly, so I added
the small subclasses FSStorage and FSDatabase to Zope2FS.
- Restored the PersistentExtra patch.
- The directory items gateway wants to write data about its children, but
sometimes its children aren't being written at the same time. Added
a "conditional" optional flag to FSConnection.writeSection(), allowing
data to be written only if other data gets written.
=== Added File Products/AdaptableStorage/zodb/public.py ===
##############################################################################
#
# Copyright (c) 2002 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.
#
##############################################################################
"""zodb public names
$Id: public.py,v 1.1 2002/12/03 23:10:55 shane Exp $
"""
from interfaces.public import *
from ASConnection import ASConnection
from ASDB import ASDB
from ASStorage import ASStorage
from OIDEncoder import OIDEncoder
from StaticResource import StaticResource
=== Products/AdaptableStorage/zodb/ASConnection.py 1.1 => 1.2 ===
--- Products/AdaptableStorage/zodb/ASConnection.py:1.1 Wed Nov 27 13:37:08 2002
+++ Products/AdaptableStorage/zodb/ASConnection.py Tue Dec 3 18:10:55 2002
@@ -24,7 +24,7 @@
from ZODB.Connection import Connection, StringIO, Unpickler, Pickler, \
ConflictError, ReadConflictError, ExtensionKlass, LOG, ERROR
-from consts import SERIAL0
+from consts import SERIAL0, DEBUG
from serial_public import IKeyedObjectSystem
@@ -228,6 +228,8 @@
# state=object.__getstate__()
mapper, key = self.getOIDInfo(oid)
ser = mapper.getSerializer()
+ if DEBUG:
+ print 'serializing', repr(oid), repr(serial)
state, ext_refs = ser.serialize(mapper, key, object, self)
if ext_refs:
oid_encoder = self._db._oid_encoder
@@ -258,6 +260,7 @@
# serial number for a newly created object
try: cache[oid]=object
except:
+ print 'YIKES!', `object.__dict__`, `cache[oid].__dict__`
# Dang, I bet its wrapped:
if hasattr(object, 'aq_base'):
cache[oid]=object.aq_base
@@ -314,6 +317,8 @@
# for k,v in state.items(): d[k]=v
mapper, key = self.getOIDInfo(oid)
ser = mapper.getSerializer()
+ if DEBUG:
+ print 'deserializing', repr(oid), repr(serial)
ser.deserialize(mapper, key, object, self, state)
if mapper.isVolatile():
=== Products/AdaptableStorage/zodb/ASStorage.py 1.1 => 1.2 ===
--- Products/AdaptableStorage/zodb/ASStorage.py:1.1 Wed Nov 27 13:37:08 2002
+++ Products/AdaptableStorage/zodb/ASStorage.py Tue Dec 3 18:10:55 2002
@@ -28,12 +28,21 @@
class ASStorage(BaseStorage.BaseStorage):
- def __init__(self, domain_resource, oid_encoder=None,
- name='AdaptableStorage ZODB backend'):
+ def __init__(self, domain_resource, tpc_conns=(),
+ oid_encoder=None, name=''):
self._domain_resource = domain_resource
if oid_encoder is None:
oid_encoder = OIDEncoder()
self._oid_encoder = oid_encoder
+ self._tpc_conns = tpc_conns
+ sort_keys = []
+ names = []
+ for c in tpc_conns:
+ sort_keys.append(c.sortKey())
+ names.append(c.getName())
+ self._sort_key = tuple(sort_keys)
+ if not name:
+ name = 'AdaptableStorage: ' + ', '.join(names)
BaseStorage.BaseStorage.__init__(self, name)
def __len__(self):
@@ -43,20 +52,16 @@
# Stub
return 1
- def hashSerial(self, serial):
- """Turns any object into an 8-byte checksum.
+ def sortKey(self):
+ return self._sort_key
- Note that this is somewhat inefficient and error-prone if the
- input includes anything besides simple objects
- (ints, tuples, strings, etc.) It seems to work for now.
+ def hashSerial(self, serial):
+ """Returns an 8-byte checksum.
"""
- s = repr(serial)
- hash = md5.new(s).digest()[:8]
- if hash == SERIAL0: # Avoid the special value.
- hash = SERIAL1
+ h = '%08x' % hash(serial)
if DEBUG:
- print 'hash of %r is %r' % (serial, hash)
- return hash
+ print 'hash of %r is %r' % (serial, h)
+ return h
def getOIDInfo(self, oid):
mapper_name, key = self._oid_encoder.decode(oid)
@@ -76,10 +81,10 @@
p.dump(class_info)
p.dump(full_state)
data = file.getvalue()
- hash = self.hashSerial(serial)
+ h = self.hashSerial(serial)
if DEBUG:
- print 'loaded', `oid`, `hash`
- return data, hash
+ print 'loaded', `oid`, `h`
+ return data, h
finally:
self._lock_release()
@@ -130,11 +135,21 @@
def _clear_temp(self):
pass
+ def _abort(self):
+ for c in self._tpc_conns:
+ c.abort()
+
+ def _begin(self, tid, u, d, e):
+ for c in self._tpc_conns:
+ c.begin()
+
def _finish(self, tid, user, desc, ext):
- pass
+ for c in self._tpc_conns:
+ c.finish()
- def _abort(self):
- pass
+ def _vote(self):
+ for c in self._tpc_conns:
+ c.vote()
def pack(self, t, referencesf):
pass