Commit 7cf6f802 authored by Jeremy Hylton's avatar Jeremy Hylton

Finish synchronizing FileStorage and POSException between ZODB3 and ZODB4.

There are few differences between the two files, except for necessary
differences because of API changes.  This change involves backporting
the new UndoError style from ZODB4.
parent 899c8260
...@@ -92,7 +92,7 @@ def tryToResolveConflict(self, oid, committedSerial, oldSerial, newpickle, ...@@ -92,7 +92,7 @@ def tryToResolveConflict(self, oid, committedSerial, oldSerial, newpickle,
unpickler.persistent_load = prfactory.persistent_load unpickler.persistent_load = prfactory.persistent_load
class_tuple = unpickler.load()[0] class_tuple = unpickler.load()[0]
if bad_class(class_tuple): if bad_class(class_tuple):
return 0 return None
newstate = unpickler.load() newstate = unpickler.load()
klass = load_class(class_tuple) klass = load_class(class_tuple)
inst = klass.__basicnew__() inst = klass.__basicnew__()
...@@ -101,7 +101,7 @@ def tryToResolveConflict(self, oid, committedSerial, oldSerial, newpickle, ...@@ -101,7 +101,7 @@ def tryToResolveConflict(self, oid, committedSerial, oldSerial, newpickle,
resolve = inst._p_resolveConflict resolve = inst._p_resolveConflict
except AttributeError: except AttributeError:
bad_classes[class_tuple] = 1 bad_classes[class_tuple] = 1
return 0 return None
old = state(self, oid, oldSerial, prfactory) old = state(self, oid, oldSerial, prfactory)
committed = state(self, oid, committedSerial, prfactory, committedData) committed = state(self, oid, committedSerial, prfactory, committedData)
...@@ -115,7 +115,7 @@ def tryToResolveConflict(self, oid, committedSerial, oldSerial, newpickle, ...@@ -115,7 +115,7 @@ def tryToResolveConflict(self, oid, committedSerial, oldSerial, newpickle,
pickler.dump(resolved) pickler.dump(resolved)
return file.getvalue(1) return file.getvalue(1)
except ConflictError: except ConflictError:
return 0 return None
except: except:
# If anything else went wrong, catch it here and avoid passing an # If anything else went wrong, catch it here and avoid passing an
# arbitrary exception back to the client. The error here will mask # arbitrary exception back to the client. The error here will mask
...@@ -124,7 +124,7 @@ def tryToResolveConflict(self, oid, committedSerial, oldSerial, newpickle, ...@@ -124,7 +124,7 @@ def tryToResolveConflict(self, oid, committedSerial, oldSerial, newpickle,
# the error so that any problems can be fixed. # the error so that any problems can be fixed.
zLOG.LOG("Conflict Resolution", zLOG.ERROR, zLOG.LOG("Conflict Resolution", zLOG.ERROR,
"Unexpected error", error=sys.exc_info()) "Unexpected error", error=sys.exc_info())
return 0 return None
class ConflictResolvingStorage: class ConflictResolvingStorage:
"Mix-in class that provides conflict resolution handling for storages" "Mix-in class that provides conflict resolution handling for storages"
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
############################################################################## ##############################################################################
"""Database connection support """Database connection support
$Id: Connection.py,v 1.79 2002/11/18 23:17:40 jeremy Exp $""" $Id: Connection.py,v 1.80 2002/12/03 18:36:29 jeremy Exp $"""
from cPickleCache import PickleCache from cPickleCache import PickleCache
from POSException import ConflictError, ReadConflictError from POSException import ConflictError, ReadConflictError
...@@ -40,7 +40,7 @@ def updateCodeTimestamp(): ...@@ -40,7 +40,7 @@ def updateCodeTimestamp():
global global_code_timestamp global global_code_timestamp
global_code_timestamp = time() global_code_timestamp = time()
ExtensionKlass=Base.__class__ ExtensionKlass = Base.__class__
class Connection(ExportImport.ExportImport): class Connection(ExportImport.ExportImport):
"""Object managers for individual object space. """Object managers for individual object space.
......
This diff is collapsed.
...@@ -11,23 +11,28 @@ ...@@ -11,23 +11,28 @@
# FOR A PARTICULAR PURPOSE # FOR A PARTICULAR PURPOSE
# #
############################################################################## ##############################################################################
"""BoboPOS-defined exceptions """ZODB-defined exceptions
$Id: POSException.py,v 1.14 2002/09/05 10:19:40 htrd Exp $""" $Id: POSException.py,v 1.15 2002/12/03 18:36:29 jeremy Exp $"""
__version__ = '$Revision: 1.14 $'.split()[-2:][0]
from string import join
from types import StringType, DictType from types import StringType, DictType
from ZODB import utils import ZODB.utils
class POSError(Exception): def _fmt_oid(oid):
return "%016x" % ZODB.utils.u64(oid)
def _fmt_undo(oid, reason):
s = reason and (": %s" % reason) or ""
return "Undo error %s%s" % (_fmt_oid(oid), s)
class POSError(StandardError):
"""Persistent object system error.""" """Persistent object system error."""
class POSKeyError(KeyError, POSError): class POSKeyError(KeyError, POSError):
"""Key not found in database.""" """Key not found in database."""
def __str__(self): def __str__(self):
return "%016x" % utils.U64(self.args[0]) return _fmt_oid(self.args[0])
class TransactionError(POSError): class TransactionError(POSError):
"""An error occured due to normal transaction processing.""" """An error occured due to normal transaction processing."""
...@@ -78,12 +83,12 @@ class ConflictError(TransactionError): ...@@ -78,12 +83,12 @@ class ConflictError(TransactionError):
def __str__(self): def __str__(self):
extras = [] extras = []
if self.oid: if self.oid:
extras.append("oid %016x" % utils.U64(self.oid)) extras.append("oid %s" % _fmt_oid(self.oid))
if self.class_name: if self.class_name:
extras.append("class %s" % self.class_name) extras.append("class %s" % self.class_name)
if self.serials: if self.serials:
extras.append("serial was %016x, now %016x" % extras.append("serial was %s, now %s" %
tuple(map(utils.U64, self.serials))) tuple(map(_fmt_oid, self.serials)))
if extras: if extras:
return "%s (%s)" % (self.message, ", ".join(extras)) return "%s (%s)" % (self.message, ", ".join(extras))
else: else:
...@@ -104,27 +109,8 @@ class ConflictError(TransactionError): ...@@ -104,27 +109,8 @@ class ConflictError(TransactionError):
def get_serials(self): def get_serials(self):
return self.serials return self.serials
class DanglingReferenceError(TransactionError):
"""The transaction stored an object A containing a reference to another
object B, but B does not exist
Instance attributes:
Aoid: oid of the object being written
Boid: referenced oid that does not have a corresponding object
"""
def __init__(self,Aoid,Boid):
self.Aoid = Aoid
self.Boid = Boid
def __str__(self):
return "from %r to %r" % (self.Aoid,self.Boid)
class ReadConflictError(ConflictError): class ReadConflictError(ConflictError):
"""A conflict was detected at read time. """Conflict detected when object was loaded.
An attempt was made to read an object that has changed in another An attempt was made to read an object that has changed in another
transaction (eg. another thread or process). transaction (eg. another thread or process).
...@@ -144,6 +130,27 @@ class BTreesConflictError(ConflictError): ...@@ -144,6 +130,27 @@ class BTreesConflictError(ConflictError):
ConflictError.__init__(self, message="BTrees conflict error") ConflictError.__init__(self, message="BTrees conflict error")
self.btree = btree_args self.btree = btree_args
class DanglingReferenceError(TransactionError):
"""An object has a persistent reference to a missing object.
If an object is stored and it has a reference to another object
that does not exist (for example, it was deleted by pack), this
exception may be raised. Whether a storage supports this feature,
it a quality of implementation issue.
Instance attributes:
referer: oid of the object being written
missing: referenced oid that does not have a corresponding object
"""
def __init__(self, Aoid, Boid):
self.referer = Aoid
self.missing = Boid
def __str__(self):
return "from %s to %s" % (_fmt_oid(self.referer),
_fmt_oid(self.missing))
class VersionError(POSError): class VersionError(POSError):
"""An error in handling versions occurred.""" """An error in handling versions occurred."""
...@@ -159,26 +166,24 @@ class VersionLockError(VersionError, TransactionError): ...@@ -159,26 +166,24 @@ class VersionLockError(VersionError, TransactionError):
class UndoError(POSError): class UndoError(POSError):
"""An attempt was made to undo a non-undoable transaction.""" """An attempt was made to undo a non-undoable transaction."""
def __init__(self, *reason):
if len(reason) == 1: reason=reason[0] def __init__(self, oid, reason=None):
self.__reason=reason self._oid = oid
self._reason = reason
def __repr__(self):
reason=self.__reason def __str__(self):
if type(reason) is not DictType: return _fmt_undo(self._oid, self._reason)
if reason: return str(reason)
return "non-undoable transaction" class MultipleUndoErrors(UndoError):
r=[] """Several undo errors occured during a single transaction."""
for oid, reason in reason.items():
if reason: def __init__(self, errs):
r.append("Couldn't undo change to %s because %s" # provide an oid and reason for clients that only look at that
% (`oid`, reason)) UndoError.__init__(self, *errs[0])
else: self._errs = errs
r.append("Couldn't undo change to %s" % (`oid`))
def __str__(self):
return join(r,'\n') return "\n".join([_fmt_undo(*pair) for pair in self._errs])
__str__=__repr__
class StorageError(POSError): class StorageError(POSError):
"""Base class for storage based exceptions.""" """Base class for storage based exceptions."""
...@@ -201,9 +206,6 @@ class TransactionTooLargeError(StorageTransactionError): ...@@ -201,9 +206,6 @@ class TransactionTooLargeError(StorageTransactionError):
class ExportError(POSError): class ExportError(POSError):
"""An export file doesn't have the right format.""" """An export file doesn't have the right format."""
class Unimplemented(POSError):
"""An unimplemented feature was used."""
class Unsupported(POSError): class Unsupported(POSError):
"""An feature that is unsupported bt the storage was used.""" """An feature that is unsupported bt the storage was used."""
......
...@@ -17,6 +17,8 @@ import TimeStamp, time ...@@ -17,6 +17,8 @@ import TimeStamp, time
from struct import pack, unpack from struct import pack, unpack
z64 = '\0'*8
if sys.version >= (2, 2): if sys.version >= (2, 2):
# Note that the distinction between ints and longs is blurred in # Note that the distinction between ints and longs is blurred in
......
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