[Zope3-checkins] CVS: Zope3/lib/python/ZODB - POSException.py:1.18 FileStorage.py:1.108

Jeremy Hylton jeremy@zope.com
Tue, 3 Dec 2002 13:38:03 -0500


Update of /cvs-repository/Zope3/lib/python/ZODB
In directory cvs.zope.org:/tmp/cvs-serv21361/ZODB

Modified Files:
	POSException.py FileStorage.py 
Log Message:
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.


=== Zope3/lib/python/ZODB/POSException.py 1.17 => 1.18 ===
--- Zope3/lib/python/ZODB/POSException.py:1.17	Thu Aug  1 12:27:01 2002
+++ Zope3/lib/python/ZODB/POSException.py	Tue Dec  3 13:38:02 2002
@@ -20,10 +20,10 @@
      import TransactionError, RollbackError, ConflictError as _ConflictError
 
 from types import StringType, DictType
-from ZODB import utils
+import ZODB.utils
 
 def _fmt_oid(oid):
-    return "%016x" % utils.u64(oid)
+    return "%016x" % ZODB.utils.u64(oid)
 
 def _fmt_undo(oid, reason):
     s = reason and (": %s" % reason) or ""
@@ -113,7 +113,7 @@
 class ReadConflictError(ConflictError):
     """Conflict detected when object was loaded.
 
-    There was an attempt 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).
     """
     def __init__(self, message=None, object=None, serials=None):
@@ -122,6 +122,27 @@
         ConflictError.__init__(self, message=message, object=object,
                                serials=serials)
 
+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):
     """An error in handling versions occurred."""
 
@@ -153,7 +174,7 @@
         return "\n".join([_fmt_undo(*pair) for pair in self._errs])
 
 class StorageError(POSError):
-    pass
+    """Base class for storage based exceptions."""
 
 class StorageTransactionError(StorageError):
     """An operation was invoked for an invalid transaction or state."""
@@ -167,9 +188,21 @@
 class ReadOnlyError(StorageError):
     """Unable to modify objects in a read-only storage."""
 
+class TransactionTooLargeError(StorageTransactionError):
+    """The transaction exhausted some finite storage resource."""
+
 class ExportError(POSError):
     """An export file doesn't have the right format."""
 
 class Unsupported(POSError):
     """An feature that is unsupported bt the storage was used."""
     
+class InvalidObjectReference(POSError):
+    """An object contains an invalid reference to another object.
+
+    An invalid reference may be one of:
+
+    o A reference to a wrapped persistent object.
+
+    o A reference to an object in a different database connection.
+    """


=== Zope3/lib/python/ZODB/FileStorage.py 1.107 => 1.108 ===
--- Zope3/lib/python/ZODB/FileStorage.py:1.107	Tue Dec  3 12:24:12 2002
+++ Zope3/lib/python/ZODB/FileStorage.py	Tue Dec  3 13:38:02 2002
@@ -219,6 +219,8 @@
     def __init__(self, file_name, create=0, read_only=0, stop=None,
                  quota=None):
 
+        # This check was removed from ZODB3, because old versions of
+        # python could lie if they didn't have large file support.
         if not os.path.exists(file_name):
             create = 1
 
@@ -327,11 +329,10 @@
         return {}, {}, {}, {}
 
     def _save_index(self):
-        """Write the database index to a file to support quick startup
-        """
+        """Write the database index to a file to support quick startup."""
 
-        index_name=self._name+'.index'
-        tmp_name=index_name+'.index_tmp'
+        index_name = self._name + '.index'
+        tmp_name = index_name + '.index_tmp'
 
         f=open(tmp_name,'wb')
         p=Pickler(f,1)
@@ -351,7 +352,7 @@
         except: pass
 
     def _clear_index(self):
-        index_name=self._name+'.index'
+        index_name = self._name + '.index'
         if os.path.exists(index_name):
             try:
                 os.remove(index_name)
@@ -596,7 +597,6 @@
             pnv = read(8) # Read location of non-version data
             if (not version or len(version) != vlen or
                 (read(8) # skip past version link
-                 and version != read(vlen)
                  and version != read(vlen))):
                 return _loadBack(file, oid, pnv)
 
@@ -692,7 +692,8 @@
                             `oid`, locked_version)
 
                 if serial != oserial:
-                    data=self.tryToResolveConflict(oid, oserial, serial, data)
+                    data = self.tryToResolveConflict(oid, oserial, serial,
+                                                     data)
                     if data is None:
                         raise POSException.ConflictError(oid=oid,
                                                 serials=(oserial, serial))
@@ -1111,7 +1112,7 @@
         if data:
             return data, 0, version, snv, ipos
 
-        raise UndoError(oid, 'Some data were modified by a later transaction')
+        raise UndoError(oid, "Some data were modified by a later transaction")
 
     # undoLog() returns a description dict that includes an id entry.
     # The id is opaque to the client, but contains the transaction id.
@@ -1160,7 +1161,6 @@
         if transaction is not self._transaction:
             raise POSException.StorageTransactionError(self, transaction)
 
-
         self._lock_acquire()
         try:
             return self._txn_undo(transaction_id)
@@ -1200,6 +1200,8 @@
         # Let's move the file pointer back to the start of the txn record.
         self._file.seek(tpos)
         h = self._file.read(TRANS_HDR_LEN)
+        if h[16] == 'u':
+            return
         if h[16] != ' ':
                 raise UndoError(None, 'non-undoable transaction')
         tl = u64(h[8:16])
@@ -1253,7 +1255,7 @@
                 here += odlen
             pos += dlen
             if pos > tend:
-                raise UndoError(None , 'non-undoable transaction')
+                raise UndoError(None , "non-undoable transaction")
         if failures:
             raise MultipleUndoErrors(failures.items())
 
@@ -1328,7 +1330,7 @@
 
                 if vlen:
                     assert read(8) != z64
-                    read(8)
+                    read(8) # Skip previous version record pointer
                     version=read(vlen)
                     if wantver is not None and version != wantver:
                         if prev:
@@ -1365,7 +1367,7 @@
     def _redundant_pack(self, file, pos):
         assert pos > 8, pos
         file.seek(pos - 8)
-        p=u64(file.read(8))
+        p = u64(file.read(8))
         file.seek(pos - p + 8)
         return file.read(1) not in ' u'
 
@@ -1961,8 +1963,6 @@
     id in the data.  The transaction id is the tid of the last
     transaction.
     """
-
-
     read = file.read
     seek = file.seek
     seek(0, 2)
@@ -2354,6 +2354,7 @@
 
 class RecordIterator(Iterator, BaseStorage.TransactionRecord):
     """Iterate over the transactions in a FileStorage file."""
+    
     def __init__(self, tid, status, user, desc, ext, pos, tend, file, tpos):
         self.tid = tid
         self.status = status
@@ -2375,7 +2376,6 @@
             prev = u64(sprev)
             tloc = u64(stloc)
             plen = u64(splen)
-
             dlen = DATA_HDR_LEN + (plen or 8)
 
             if vlen: