[Zope-CVS] CVS: Products/AdaptableStorage/zodb - ASStorage.py:1.10

Shane Hathaway shane@zope.com
Thu, 9 Jan 2003 09:34:11 -0500


Update of /cvs-repository/Products/AdaptableStorage/zodb
In directory cvs.zope.org:/tmp/cvs-serv19323/zodb

Modified Files:
	ASStorage.py 
Log Message:
- Added LoadEvent and StoreEvent, which currently serve only to
clarify the code.

- Added tests of conflict detection.

- Added NoStateFoundError.  Classification gateways now raise
NoStateFoundError at the right times so it's possible to detect
attempts to overwrite state with new objects

- Made it easier for a SQL gateway to use multiple tables by adding a
setupTables() method to SQLGatewayBase

- Made FieldSchema.addFieldType public.



=== Products/AdaptableStorage/zodb/ASStorage.py 1.9 => 1.10 ===
--- Products/AdaptableStorage/zodb/ASStorage.py:1.9	Tue Dec 31 16:47:52 2002
+++ Products/AdaptableStorage/zodb/ASStorage.py	Thu Jan  9 09:34:08 2003
@@ -21,7 +21,9 @@
 from cStringIO import StringIO
 
 from ZODB import POSException, BaseStorage
-from mapper_public import MapperEvent, ITPCConnection
+from mapper_public \
+     import MapperEvent, LoadEvent, StoreEvent, \
+     ITPCConnection, NoStateFoundError
 
 from consts import SERIAL0, SERIAL1, DEBUG
 from OIDEncoder import OIDEncoder
@@ -90,14 +92,14 @@
             k = keychain[:i + 1]
             cfr = mapper.getClassifier()
             assert cfr is not None, keychain
-            event = MapperEvent(mapper, k)
+            event = LoadEvent(mapper, k)
             classification, sub_mapper_name = cfr.classifyState(event)
             mapper_names.append(sub_mapper_name)
             mapper = mapper.getSubMapper(sub_mapper_name)
-        event = MapperEvent(mapper, keychain)
+        event = LoadEvent(mapper, keychain)
         full_state, serial = mapper.getGateway().load(event)
         return full_state, serial, classification, mapper_names
-        
+
 
     def load(self, oid, version):
         if version:
@@ -138,12 +140,29 @@
             if DEBUG:
                 print 'storing', `oid`, `serial_hash`
             if serial_hash != SERIAL0:
+                # Overwriting an old object.  Use the serial to verify
+                # that the new data was derived from the old data.
                 info = self._load(root_mapper, keychain)
                 old_state, old_serial = info[:2]
                 old_serial_hash = self.hashSerial(old_serial)
                 if serial_hash != old_serial_hash:
-                    raise POSException.ConflictError("%r != %r" % (
-                        serial_hash, old_serial_hash))
+                    raise POSException.ConflictError(
+                        "Storing %s based on old data. %s != %s" % (
+                        repr(keychain),
+                        repr(serial_hash), repr(old_serial_hash)))
+            else:
+                # A new object.  Attempts to load should lead to
+                # NoStateFoundError or a serial of None, otherwise
+                # there's a conflict.
+                try:
+                    info = self._load(root_mapper, keychain)
+                except NoStateFoundError:
+                    pass
+                else:
+                    old_serial = info[1]
+                    if old_serial is not None:
+                        raise POSException.ConflictError(
+                            "%s already exists" % repr(keychain))
 
             # Now unpickle and store the data.
             file = StringIO(data)
@@ -156,7 +175,7 @@
             for mapper_name in mapper_names:
                 cfr = mapper.getClassifier()
                 mapper = mapper.getSubMapper(mapper_name)
-            event = MapperEvent(mapper, keychain)
+            event = StoreEvent(mapper, keychain)
             new_serial = mapper.getGateway().store(event, state)
             if cfr is not None:
                 cfr.store(event, classification)