[Checkins] SVN: gocept.zeoraid/trunk/ - Started `known issues` file and documented API compatibility for versions.

Christian Theune ct at gocept.com
Mon Jan 14 07:20:42 EST 2008


Log message for revision 82867:
  - Started `known issues` file and documented API compatibility for versions.
  - Completed tests for history support.
  - API compatibility for ZODB 3.9 and lower.
  - Switched to ZODB 3.9
  

Changed:
  A   gocept.zeoraid/trunk/KNOWNISSUES.txt
  U   gocept.zeoraid/trunk/setup.py
  U   gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py
  U   gocept.zeoraid/trunk/src/gocept/zeoraid/tests/failingstorage.py
  U   gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py

-=-
Added: gocept.zeoraid/trunk/KNOWNISSUES.txt
===================================================================
--- gocept.zeoraid/trunk/KNOWNISSUES.txt	                        (rev 0)
+++ gocept.zeoraid/trunk/KNOWNISSUES.txt	2008-01-14 12:20:40 UTC (rev 82867)
@@ -0,0 +1,13 @@
+============
+Known issues
+============
+
+
+Compatibility with ZODB `versions`
+==================================
+
+ZEORaid is not compatible with ZODB versions as those are being deprecated and
+actively removed.
+
+ZEORaid has API-compatibility with releases of the ZODB that provide and use
+versions but will actively prevent any usage of the version features.


Property changes on: gocept.zeoraid/trunk/KNOWNISSUES.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: gocept.zeoraid/trunk/setup.py
===================================================================
--- gocept.zeoraid/trunk/setup.py	2008-01-14 03:01:53 UTC (rev 82866)
+++ gocept.zeoraid/trunk/setup.py	2008-01-14 12:20:40 UTC (rev 82867)
@@ -18,7 +18,7 @@
     package_dir = {'':'src'},
     namespace_packages = ['gocept'],
     install_requires = ['setuptools',
-                        'ZODB3<3.9dev',
+                        'ZODB3>=3.9dev',
                         'zope.component'],
     extras_require = {
         'recipe': ['zc.buildout']

Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py	2008-01-14 03:01:53 UTC (rev 82866)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py	2008-01-14 12:20:40 UTC (rev 82867)
@@ -28,7 +28,39 @@
         return method(self, *args, **kw)
     return check_open
 
+no_transaction_marker = object()
 
+def choose_transaction(version, transaction):
+    # In ZODB < 3.9 both version and transaction are required positional
+    # arguments.
+    # In ZODB >= 3.9 the version argument is gone and transaction takes it
+    # place in the positional order.
+    if transaction is no_transaction_marker:
+        # This looks like a ZODB 3.9 client, so we clean up the order.
+        transaction = version
+        version = ''
+    # XXX For compatibility only version == '  is relevant. The ZODB is still 
+    # being changed for removing versions though and the tests might pass in 0
+    # for now.
+    assert version == '' or version == 0
+    return transaction
+
+def store_38_compatible(method):
+    def prepare_store(self, oid, oldserial, data, version='',
+                      transaction=no_transaction_marker):
+        transaction = choose_transaction(version, transaction)
+        return method(self, oid, oldserial, data, transaction)
+    return prepare_store
+
+
+def storeBlob_38_compatible(method):
+    def prepare_store(self, oid, oldserial, data, blob, version='',
+                      transaction=no_transaction_marker):
+        transaction = choose_transaction(version, transaction)
+        return method(self, oid, oldserial, data, blob, transaction)
+    return prepare_store
+
+
 class RAIDStorage(object):
     """The RAID storage is a drop-in replacement for the client storages that
     are configured.
@@ -132,9 +164,10 @@
         """An approximate size of the database, in bytes."""
         return self._apply_single_storage('getSize')
 
-    def history(self, oid, version=None, size=1):
+    def history(self, oid, version='', size=1):
         """Return a sequence of history information dictionaries."""
-        return self._apply_single_storage('history', oid, version, size)
+        assert version is ''
+        return self._apply_single_storage('history', oid, size)
 
     def isReadOnly(self):
         """Test whether a storage allows committing new transactions."""
@@ -148,9 +181,10 @@
         """The approximate number of objects in the storage."""
         return self._apply_single_storage('__len__')
 
-    def load(self, oid, version):
+    def load(self, oid, version=''):
         """Load data for an object id and version."""
-        return self._apply_single_storage('load', oid, version)
+        assert version is ''
+        return self._apply_single_storage('load', oid)
 
     def loadBefore(self, oid, tid):
         """Load the object data written before a transaction id."""
@@ -188,7 +222,8 @@
         return id(self)
 
     # XXX
-    def store(self, oid, oldserial, data, version, transaction):
+    @store_38_compatible
+    def store(self, oid, oldserial, data, transaction):
         if self.isReadOnly():
             raise ZODB.POSException.ReadOnlyError()
         if transaction is not self._transaction:
@@ -196,8 +231,8 @@
 
         self._lock_acquire()
         try:
-            self._apply_all_storages('store', oid, oldserial, data, version, 
-                                     transaction)
+            # XXX ClientStorage doesn't adhere to the interface correctly (yet).
+            self._apply_all_storages('store', oid, oldserial, data, '', transaction)
             if self._log_stores:
                 oids = self._unrecovered_transactions.setdefault(self._tid, [])
                 oids.append(oid)
@@ -306,7 +341,8 @@
 
     # IBlobStorage
 
-    def storeBlob(self, oid, oldserial, data, blob, version, transaction):
+    @storeBlob_38_compatible
+    def storeBlob(self, oid, oldserial, data, blob, transaction):
         """Stores data that has a BLOB attached."""
         # XXX
 
@@ -434,15 +470,18 @@
     @ensure_open_storage
     def _apply_single_storage(self, method_name, *args, **kw):
         # Try to find a storage that we can talk to. Stop after we found a reliable result.
+        failed = 0
         for name in self.storages_optimal[:]:
             # XXX storage might be degraded by now, need to check.
             storage = self.storages[name]
             method = getattr(storage, method_name)
             try:
                 result = method(*args, **kw)
-            except ZEO.ClientStorage.ClientDisconnected:
-                # XXX find other possible exceptions
-                pass
+            except Exception:
+                # XXX Logging
+                if failed:
+                    raise
+                failed += 1
             else:
                 if storage.is_connected():
                     # We have a result that is reliable.

Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/tests/failingstorage.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/tests/failingstorage.py	2008-01-14 03:01:53 UTC (rev 82866)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/tests/failingstorage.py	2008-01-14 12:20:40 UTC (rev 82867)
@@ -17,10 +17,23 @@
 
 class FailingStorage(ZODB.MappingStorage.MappingStorage):
 
+    _fail = None
+
     def getExtensionMethods(self):
         return dict(fail=None)
 
+    def history(self, *args, **kw):
+        if 'history' == self._fail:
+            raise Exception()
+        return ZODB.MappingStorage.MappingStorage.history(self, *args, **kw)
+
     def fail(self, method):
+        if method in ['history']:
+            # Those methods are copied/references by the server code, we can't
+            # rebind them here.
+            self._fail = method
+            return
+
         old_method = getattr(self, method)
         def failing_method(*args, **kw):
             setattr(self, method, old_method)

Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py	2008-01-14 03:01:53 UTC (rev 82866)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py	2008-01-14 12:20:40 UTC (rev 82867)
@@ -201,7 +201,21 @@
         self.assertEquals(32, self._storage.getSize())
         self.assertEquals('optimal', self._storage.raid_status())
 
+    def test_history(self):
+        self.assertEquals((), self._backend(0).history(ZODB.utils.z64, ''))
+        self.assertEquals((), self._backend(1).history(ZODB.utils.z64, ''))
+        self.assertEquals((), self._storage.history(ZODB.utils.z64, ''))
 
+    def test_history_degrading(self):
+        self._backend(0).fail('history')
+        self.assertEquals((), self._storage.history(ZODB.utils.z64, ''))
+        self.assertEquals('degraded', self._storage.raid_status())
+        self._backend(0).fail('history')
+        self.assertRaises(gocept.zeoraid.interfaces.RAIDError,
+                          self._storage.history, ZODB.utils.z64, '')
+        self.assertEquals('failed', self._storage.raid_status())
+
+
 class ZEOReplicationStorageTests(ZEOStorageBackendTests,
                                  ReplicationStorageTests,
                                  ThreadTests.ThreadTests):



More information about the Checkins mailing list