[Zope3-checkins] CVS: Zope3/lib/python/ZODB - FileStorage.py:1.96 POSException.py:1.15
Jeremy Hylton
jeremy@zope.com
Thu, 25 Jul 2002 17:32:11 -0400
Update of /cvs-repository/Zope3/lib/python/ZODB
In directory cvs.zope.org:/tmp/cvs-serv22988/ZODB
Modified Files:
FileStorage.py POSException.py
Log Message:
Rationalize use of UndoError().
=== Zope3/lib/python/ZODB/FileStorage.py 1.95 => 1.96 ===
import ZODB.DB
from ZODB import BaseStorage, ConflictResolution, POSException
-from ZODB.POSException import UndoError, POSKeyError
+from ZODB.POSException import UndoError, POSKeyError, MultipleUndoErrors
from ZODB.TimeStamp import TimeStamp
from ZODB.lock_file import lock_file
from ZODB.utils import t32, p64, U64, cp
@@ -148,6 +148,8 @@
DATA_HDR_LEN = 42
DATA_VERSION_HDR_LEN = 58
+packed_version='FS21'
+
def warn(message, *data):
LOG('ZODB FS',WARNING, "%s warn: %s\n"
% (packed_version, (message % data)))
@@ -159,9 +161,8 @@
LOG('ZODB FS',PANIC,"%s ERROR: %s\n" % (packed_version, (message % data)))
def panic(message, *data):
- message=message%data
- LOG('ZODB FS',PANIC,"%s ERROR: %s\n" % (packed_version, message))
- raise CorruptedTransactionError, message
+ LOG('ZODB FS',PANIC,"%s ERROR: %s\n" % (packed_version, (message % data)))
+ raise CorruptedTransactionError(message)
class FileStorageError(POSException.StorageError):
pass
@@ -174,11 +175,13 @@
class CorruptedFileStorageError(FileStorageError,
POSException.StorageSystemError):
- """Corrupted file storage
- """
+ """Corrupted file storage."""
+
+class CorruptedTransactionError(CorruptedFileStorageError):
+ pass
-class CorruptedTransactionError(CorruptedFileStorageError): pass
-class CorruptedDataError(CorruptedFileStorageError): pass
+class CorruptedDataError(CorruptedFileStorageError):
+ pass
class FileStorageQuotaError(FileStorageError,
POSException.StorageSystemError):
@@ -196,8 +199,6 @@
version_cache_deactivate_after)
return db
-packed_version='FS21'
-
class FileStorage(BaseStorage.BaseStorage,
ConflictResolution.ConflictResolvingStorage):
_packt=z64
@@ -548,7 +549,7 @@
h = self._file.read(34)
_oid = h[:8]
if _oid != oid:
- raise CorruptedData, h
+ raise CorruptedDataError(h)
vlen = unpack(">H", h[-2:])[0]
if vlen:
# If there is a version, find out its name and let
@@ -611,7 +612,7 @@
seek(pos)
h=read(DATA_HDR_LEN)
doid,dserial,prev,tloc,vlen,plen = unpack(">8s8s8s8sH8s", h)
- if doid != oid: raise CorruptedDataError, h
+ if doid != oid: raise CorruptedDataError(h)
if dserial == serial: break # Yeee ha!
# Keep looking for serial
pos=U64(prev)
@@ -640,7 +641,7 @@
seek(pos)
doid,serial,prev,tloc,vlen = unpack(">8s8s8s8sH", file.read(34))
if doid != oid:
- raise CorruptedDataError, pos
+ raise CorruptedDataError(pos)
if vlen:
seek(24,1) # skip plen, pnv, and pv
return file.read(vlen)
@@ -663,7 +664,7 @@
read=file.read
h=read(DATA_HDR_LEN)
doid,oserial,sprev,stloc,vlen,splen = unpack(">8s8s8s8sH8s", h)
- if doid != oid: raise CorruptedDataError, h
+ if doid != oid: raise CorruptedDataError(h)
if vlen:
pnv=read(8) # non-version data pointer
read(8) # skip past version link
@@ -749,7 +750,7 @@
h = self._file.read(42)
doid,oserial,sprev,stloc,vlen,splen = unpack(">8s8s8s8sH8s", h)
if doid != oid:
- raise CorruptedDataError, h
+ raise CorruptedDataError(h)
# Calculate the file position in the temporary file
here = self._pos + self._tfile.tell() + self._thl
# And update the temp file index
@@ -899,7 +900,8 @@
file.seek(pos)
h=read(DATA_HDR_LEN)
roid,serial,sprev,stloc,vlen,splen = unpack(">8s8s8s8sH8s", h)
- if roid != oid: raise UndoError('Invalid undo transaction id')
+ if roid != oid:
+ raise UndoError(oid, 'Invalid undo transaction id')
if vlen:
read(16) # skip nv pointer and version previous pointer
version=read(vlen)
@@ -954,29 +956,27 @@
oid, ipos, tpos)
# Versions of undone record and current record *must* match!
if cver != version:
- raise UndoError('Current and undone versions differ')
+ raise UndoError(oid, 'Current and undone versions differ')
if cdataptr != pos:
# We aren't sure if we are talking about the same data
try:
- if (
- # The current record wrote a new pickle
- cdataptr == tipos
- or
+ if (# The current record wrote a new pickle
+ cdataptr == tipos or
# Backpointers are different
_loadBackPOS(self._file, oid, p64(pos)) !=
_loadBackPOS(self._file, oid, p64(cdataptr))
):
if pre and not tpos:
- copy=0 # we'll try to do conflict resolution
+ copy = 0 # we'll try to do conflict resolution
else:
# We bail if:
# - We don't have a previous record, which should
# be impossible.
- raise UndoError
+ raise UndoError(oid, "No previous record")
except KeyError:
# LoadBack gave us a key error. Bail.
- raise UndoError
+ raise UndoError(oid, "_loadBack() failed")
version, snv = self._getVersion(oid, pre)
if copy:
@@ -988,13 +988,13 @@
bdata = _loadBack(self._file, oid, p64(pre))[0]
except KeyError:
# couldn't find oid; what's the real explanation for this?
- raise UndoError("_loadBack() failed for %s" % repr(oid))
+ raise UndoError(oid, "_loadBack() failed")
data=self.tryToResolveConflict(oid, cserial, serial, bdata, cdata)
if data:
return data, 0, version, snv, ipos
- raise UndoError('Some data were modified by a later transaction')
+ raise UndoError(oid, 'Some data were modified by a later transaction')
def transactionalUndo(self, transaction_id, transaction):
"""Undo a transaction, given by transaction_id.
@@ -1024,11 +1024,11 @@
self._file.seek(tpos)
h = self._file.read(TRANS_HDR_LEN)
if len(h) != TRANS_HDR_LEN or h[:8] != tid:
- raise UndoError, 'Invalid undo transaction id'
+ raise UndoError(None, 'Invalid undo transaction id')
if h[16] == 'u':
return
if h[16] != ' ':
- raise UndoError, 'non-undoable transaction'
+ raise UndoError(None, 'non-undoable transaction')
tl = U64(h[8:16])
ul, dl, el = struct.unpack(">HHH", h[17:TRANS_HDR_LEN])
tend = tpos + tl
@@ -1082,9 +1082,15 @@
pos=pos+dlen
if pos > tend:
- raise UndoError, 'non-undoable transaction'
+ raise UndoError(None, 'non-undoable transaction')
- if failures: raise UndoError(failures)
+ if failures:
+ vals = failures.values()
+ if len(vals) == 1:
+ raise vals[0]
+ else:
+ raise MultipleUndoErrors([(e._oid, e._reason)
+ for e in vals])
self._tindex.update(tindex)
return tindex.keys()
@@ -1096,8 +1102,8 @@
try:
packt=self._packt
if packt is None:
- raise UndoError(
- 'Undo is currently disabled for database maintenance.<p>')
+ raise UndoError(None,
+ 'Undo is currently disabled for database maintenance.')
pos=self._pos
if pos < 39: return []
file=self._file
@@ -1652,10 +1658,10 @@
# first 8 bytes are oid, second 8 bytes are serialno
h = self._file.read(16)
if len(h) < 16:
- raise CorruptedDataError, h
+ raise CorruptedDataError(h)
if h[:8] != oid:
h = h + self._file.read(26) # get rest of header
- raise CorruptedDataError, h
+ raise CorruptedDataError(h)
return h[8:]
def shift_transactions_forward(index, vindex, tindex, file, pos, opos):
=== Zope3/lib/python/ZODB/POSException.py 1.14 => 1.15 ===
from types import StringType, DictType
from ZODB import utils
+def _fmt_oid(oid):
+ return "%016x" % 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."""
@@ -29,7 +36,7 @@
"""Key not found in database."""
def __str__(self):
- return "%016x" % utils.U64(self.args[0])
+ return _fmt_oid(self.args[0])
class ConflictError(_ConflictError):
"""Two transactions tried to modify the same object at once.
@@ -77,12 +84,12 @@
def __str__(self):
extras = []
if self.oid:
- extras.append("oid %016x" % utils.U64(self.oid))
+ extras.append("oid %016x" % _fmt_oid(self.oid))
if self.class_name:
extras.append("class %s" % self.class_name)
if self.serials:
extras.append("serial was %016x, now %016x" %
- tuple(map(utils.U64, self.serials)))
+ tuple(map(_fmt_oid, self.serials)))
if extras:
return "%s (%s)" % (self.message, ", ".join(extras))
else:
@@ -103,7 +110,6 @@
def get_serials(self):
return self.serials
-
class ReadConflictError(ConflictError):
"""Conflict detected when object was loaded.
@@ -127,28 +133,24 @@
class UndoError(POSError):
"""An attempt was made to undo a non-undoable transaction."""
-
- def __init__(self, *reason):
- if len(reason) == 1:
- reason = reason[0]
- self.__reason = reason
-
- def __repr__(self):
- reason=self.__reason
- if type(reason) is not DictType:
- if reason: return str(reason)
- return "non-undoable transaction"
- r=[]
- for oid, reason in reason.items():
- if reason:
- r.append("Couldn't undo change to %s because %s"
- % (`oid`, reason))
- else:
- r.append("Couldn't undo change to %s" % (`oid`))
- return "\n".join(r)
+ def __init__(self, oid, reason=None):
+ self._oid = oid
+ self._reason = reason
- __str__=__repr__
+ def __str__(self):
+ return _fmt_undo(self._oid, self._reason)
+
+class MultipleUndoErrors(UndoError):
+ """Several undo errors occured during a single transaction."""
+
+ def __init__(self, errs):
+ # provide an oid and reason for clients that only look at that
+ UndoError.__init__(self, *errs[0])
+ self._errs = errs
+
+ def __str__(self):
+ return "\n".join([_fmt_undo(*pair) for pair in self._errs])
class StorageError(POSError):
pass