[Checkins] SVN: gocept.zeoraid/trunk/src/gocept/zeoraid/ merged distributed-remote-calls branch

Thomas Lotze tl at gocept.com
Wed Jan 7 09:45:20 EST 2009


Log message for revision 94581:
  merged distributed-remote-calls branch

Changed:
  U   gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py
  U   gocept.zeoraid/trunk/src/gocept/zeoraid/tests/component.xml
  A   gocept.zeoraid/trunk/src/gocept/zeoraid/tests/loggingstorage.py
  U   gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py

-=-
Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py	2009-01-07 14:44:41 UTC (rev 94580)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py	2009-01-07 14:45:19 UTC (rev 94581)
@@ -20,6 +20,7 @@
 import os
 import os.path
 import shutil
+import random
 
 import zc.lockfile
 import zope.interface
@@ -617,10 +618,16 @@
 
     @ensure_open_storage
     def _apply_single_storage(self, method_name, args=(), kw={}):
-        """Calls the given method on the first optimal storage."""
+        """Calls the given method on a random optimal storage."""
         # Try to find a storage that we can talk to. Stop after we found a
         # reliable result.
-        for name in self.storages_optimal[:]:
+        storages = self.storages_optimal[:]
+        reliable = False
+        while not reliable:
+            if not storages:
+                break
+            name = random.choice(storages)
+            storages.remove(name)
             reliable, result = self.__apply_storage(
                 name, method_name, args, kw)
             if reliable:

Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/tests/component.xml
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/tests/component.xml	2009-01-07 14:44:41 UTC (rev 94580)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/tests/component.xml	2009-01-07 14:45:19 UTC (rev 94581)
@@ -2,12 +2,12 @@
 
 <!-- Support for unit testing with storages that simulate errors. -->
 
-<component prefix="gocept.zeoraid.tests.failingstorage">
+<component prefix="gocept.zeoraid.tests">
 
     <sectiontype
         name="failingstorage"
         implements="ZODB.storage"
-        datatype=".Opener">
+        datatype=".failingstorage.Opener">
 
       <key name="blob-dir" required="no">
         <description>
@@ -17,4 +17,14 @@
 
     </sectiontype>
 
+    <sectiontype 
+        name="loggingstorage" 
+        implements="ZODB.storage"
+        datatype=".loggingstorage.Opener">
+      
+      <key name="name" default="Logging Storage"/>
+      <section type="ZODB.storage" name="*" attribute="base"/>
+
+    </sectiontype>
+
 </component>

Added: gocept.zeoraid/trunk/src/gocept/zeoraid/tests/loggingstorage.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/tests/loggingstorage.py	                        (rev 0)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/tests/loggingstorage.py	2009-01-07 14:45:19 UTC (rev 94581)
@@ -0,0 +1,41 @@
+##############################################################################
+#
+# Copyright (c) 2007-2008 Zope Foundation and contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""LoggingStorage is a storage used for testing purposes that logs calls made
+   to an arbitrary method (getSize()).
+"""
+
+import tempfile
+
+import ZODB.config
+import ZODB.FileStorage
+
+
+class Opener(ZODB.config.BaseConfig):
+
+    def open(self):
+        name = self.config.name
+        file_handle, file_name = tempfile.mkstemp()
+        return LoggingStorage(name, file_name)
+
+
+class LoggingStorage(ZODB.FileStorage.FileStorage):
+
+    def __init__(self, name='', file_name=''):
+        ZODB.FileStorage.FileStorage.__init__(self, file_name)
+        self._name = name
+        self._log = []
+
+    def getSize(self):
+        self._log.append("Storage '%s' called." % self._name)
+        return ZODB.FileStorage.FileStorage.getSize(self)


Property changes on: gocept.zeoraid/trunk/src/gocept/zeoraid/tests/loggingstorage.py
___________________________________________________________________
Added: svn:keywords
   + Id Rev Date
Added: svn:eol-style
   + native

Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py	2009-01-07 14:44:41 UTC (rev 94580)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py	2009-01-07 14:45:19 UTC (rev 94581)
@@ -13,6 +13,7 @@
 ##############################################################################
 """Test harness for gocept.zeoraid."""
 
+import random
 import unittest
 import tempfile
 import os
@@ -36,6 +37,7 @@
 
 import gocept.zeoraid.storage
 import gocept.zeoraid.tests.test_recovery
+from gocept.zeoraid.tests.loggingstorage import LoggingStorage
 
 from ZEO.ClientStorage import ClientStorage
 from ZEO.tests import forker, CommitLockTests, ThreadTests
@@ -180,6 +182,9 @@
         self._storage = gocept.zeoraid.storage.RAIDStorage(
             'teststorage', self._storages, blob_dir=blob_dir)
 
+        self.orig_choice = random.choice
+        random.choice = lambda seq: seq[0]
+
     def tearDown(self):
         self._storage.close()
         for server in self._servers:
@@ -189,7 +194,9 @@
         for path in self.temp_paths:
             shutil.rmtree(path)
 
+        random.choice = self.orig_choice
 
+
 class FailingStorageSharedBlobTestSetup(FailingStorageTestSetup):
 
     def setUp(self):
@@ -219,7 +226,10 @@
             'teststorage', self._storages, blob_dir=blob_dir,
             shared_blob_dir=True)
 
+        self.orig_choice = random.choice
+        random.choice = lambda seq: seq[0]
 
+
 class FailingStorageTestBase(object):
 
     def _disable_storage(self, index):
@@ -1389,9 +1399,55 @@
     raise Exception()
 
 
+class LoggingStorageOpener(object):
+
+    def __init__(self, name, **kwargs):
+        self.name = name
+        self.file_handle, self.file_name = tempfile.mkstemp()
+
+    def open(self, **kwargs):
+        return LoggingStorage(self.name, self.file_name)
+
+
+class LoggingStorageDistributedTests(StorageTestBase.StorageTestBase):
+
+    # The backend and call counts have been chosen such that the probability
+    # of all calls being served by the same backend is about 1:10^6.
+    backend_count = 10
+    call_count = 6
+
+    def _backend(self, index):
+        return self._storage.storages[
+            self._storage.storages_optimal[index]]
+
+    def setUp(self):
+        self._storages = []
+        for i in xrange(self.backend_count):
+            self._storages.append(LoggingStorageOpener(str(i)))
+        self._storage = gocept.zeoraid.storage.RAIDStorage(
+            'teststorage', self._storages)
+
+    def tearDown(self):
+        self._storage.close()
+
+    def test_distributed_single_calls(self):
+        for i in xrange(self.call_count):
+            self._storage.getSize()
+
+        # assert that at least two storages gets called at least one time
+        storages_called = [x for x in xrange(self.backend_count)
+                           if len(self._backend(x)._log) >= 1]
+        self.assertEquals(storages_called >= 2, True)
+
+        # assert that six calls were made
+        self.assertEquals(6, sum([len(self._backend(x)._log)
+                                  for x in xrange(self.backend_count)]))
+
+
 def test_suite():
     suite = unittest.TestSuite()
     suite.addTest(unittest.makeSuite(ZEOReplicationStorageTests, "check"))
     suite.addTest(unittest.makeSuite(FailingStorageTests))
     suite.addTest(unittest.makeSuite(FailingStorageSharedBlobTests))
+    suite.addTest(unittest.makeSuite(LoggingStorageDistributedTests))
     return suite



More information about the Checkins mailing list