[Checkins] SVN: relstorage/branches/1.1/ merged from the trunk (-r94948:94998)

Shane Hathaway shane at hathawaymix.org
Sun Jan 25 01:31:46 EST 2009


Log message for revision 95000:
  merged from the trunk (-r94948:94998)

Changed:
  _U  relstorage/branches/1.1/
  U   relstorage/branches/1.1/CHANGES.txt
  A   relstorage/branches/1.1/bootstrap.py
  A   relstorage/branches/1.1/buildout.cfg
  A   relstorage/branches/1.1/notes/migrate-to-1.1.2.txt
  U   relstorage/branches/1.1/relstorage/__init__.py
  U   relstorage/branches/1.1/relstorage/adapters/common.py
  U   relstorage/branches/1.1/relstorage/adapters/mysql.py
  U   relstorage/branches/1.1/relstorage/adapters/oracle.py
  U   relstorage/branches/1.1/relstorage/adapters/postgresql.py
  U   relstorage/branches/1.1/relstorage/config.py
  U   relstorage/branches/1.1/relstorage/relstorage.py
  U   relstorage/branches/1.1/relstorage/tests/alltests.py
  A   relstorage/branches/1.1/relstorage/tests/fakecache.py
  U   relstorage/branches/1.1/relstorage/tests/reltestbase.py
  U   relstorage/branches/1.1/relstorage/tests/speedtest.py
  U   relstorage/branches/1.1/relstorage/tests/testmysql.py
  U   relstorage/branches/1.1/relstorage/tests/testoracle.py
  U   relstorage/branches/1.1/relstorage/tests/testpostgresql.py
  U   relstorage/branches/1.1/relstorage/zodbconvert.py
  U   relstorage/branches/1.1/setup.py

-=-

Property changes on: relstorage/branches/1.1
___________________________________________________________________
Modified: svn:ignore
   - nbproject

   + nbproject
develop-eggs
parts
.installed.cfg
coverage
bin
RelStorage.egg-info


Modified: relstorage/branches/1.1/CHANGES.txt
===================================================================
--- relstorage/branches/1.1/CHANGES.txt	2009-01-25 06:24:52 UTC (rev 94999)
+++ relstorage/branches/1.1/CHANGES.txt	2009-01-25 06:31:46 UTC (rev 95000)
@@ -1,7 +1,17 @@
-Version 1.1.2 (unreleased)
+Next Release
 
+- Refined the pack algorithm.  It was not removing as many object states
+  as it should have.  As a bonus, there is now a method of adapters called
+  fill_object_refs(), which could be useful for debugging.  It ensures the
+  object_ref table is fully populated.
 
+- Began using zc.buildout for development.
 
+- Increased automated test coverage.
+
+- Fixed KeyError reporting to not trip over a related KeyError while logging.
+
+
 Version 1.1.1 (2008-12-27)
 
 - Worked around MySQL performance bugs in packing.  Used temporary

Copied: relstorage/branches/1.1/bootstrap.py (from rev 94998, relstorage/trunk/bootstrap.py)
===================================================================
--- relstorage/branches/1.1/bootstrap.py	                        (rev 0)
+++ relstorage/branches/1.1/bootstrap.py	2009-01-25 06:31:46 UTC (rev 95000)
@@ -0,0 +1,54 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation 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.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id: bootstrap.py,v 1.1 2009/01/10 15:13:39 shane Exp $
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+ez = {}
+exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                     ).read() in ez
+ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+# use pkg_resources from the package just downloaded.
+del sys.modules['pkg_resources']
+import pkg_resources
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+    cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+    os.P_WAIT, sys.executable, sys.executable,
+    '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
+    dict(os.environ,
+         PYTHONPATH=
+         ws.find(pkg_resources.Requirement.parse('setuptools')).location
+         ),
+    ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)

Copied: relstorage/branches/1.1/buildout.cfg (from rev 94998, relstorage/trunk/buildout.cfg)
===================================================================
--- relstorage/branches/1.1/buildout.cfg	                        (rev 0)
+++ relstorage/branches/1.1/buildout.cfg	2009-01-25 06:31:46 UTC (rev 95000)
@@ -0,0 +1,28 @@
+[buildout]
+develop = .
+parts = test python coverage-test coverage-report
+find-links = http://packages.willowrise.org
+versions = versions
+
+[versions]
+ZODB3 = 3.8.1-polling
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = relstorage
+
+[python]
+recipe = zc.recipe.egg
+eggs = relstorage
+interpreter = python
+
+[coverage-test]
+recipe = zc.recipe.testrunner
+eggs = relstorage
+defaults = ['--coverage', '../../coverage']
+
+[coverage-report]
+recipe = zc.recipe.egg
+eggs = z3c.coverage
+scripts = coverage=coverage-report
+arguments = ('coverage', 'coverage/report')

Copied: relstorage/branches/1.1/notes/migrate-to-1.1.2.txt (from rev 94998, relstorage/trunk/notes/migrate-to-1.1.2.txt)
===================================================================
--- relstorage/branches/1.1/notes/migrate-to-1.1.2.txt	                        (rev 0)
+++ relstorage/branches/1.1/notes/migrate-to-1.1.2.txt	2009-01-25 06:31:46 UTC (rev 95000)
@@ -0,0 +1,13 @@
+
+Migrating from RelStorage version 1.1.1 to version 1.1.2
+
+Before following these directions, first upgrade to the schema of
+RelStorage version 1.1.1 by following the directions in "migrate-to-1.1.1.txt".
+
+Only Oracle needs a schema update for this release:
+
+    DROP TABLE temp_pack_visit;
+    CREATE GLOBAL TEMPORARY TABLE temp_pack_visit (
+        zoid        NUMBER(20) NOT NULL PRIMARY KEY,
+        keep_tid    NUMBER(20)
+    );

Modified: relstorage/branches/1.1/relstorage/__init__.py
===================================================================
--- relstorage/branches/1.1/relstorage/__init__.py	2009-01-25 06:24:52 UTC (rev 94999)
+++ relstorage/branches/1.1/relstorage/__init__.py	2009-01-25 06:31:46 UTC (rev 95000)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2008 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,

Modified: relstorage/branches/1.1/relstorage/adapters/common.py
===================================================================
--- relstorage/branches/1.1/relstorage/adapters/common.py	2009-01-25 06:24:52 UTC (rev 94999)
+++ relstorage/branches/1.1/relstorage/adapters/common.py	2009-01-25 06:31:46 UTC (rev 95000)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2008 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -67,7 +67,8 @@
 
         'create_temp_pack_visit': """
             CREATE TEMPORARY TABLE temp_pack_visit (
-                zoid BIGINT NOT NULL
+                zoid BIGINT NOT NULL,
+                keep_tid BIGINT
             );
             CREATE UNIQUE INDEX temp_pack_visit_zoid ON temp_pack_visit (zoid)
             """,
@@ -96,6 +97,7 @@
                     SELECT DISTINCT to_zoid
                     FROM object_ref
                         JOIN temp_pack_visit USING (zoid)
+                    WHERE object_ref.tid >= temp_pack_visit.keep_tid
                 )
             """,
 
@@ -528,12 +530,9 @@
         if stmt:
             self._run_script(cursor, stmt)
 
-        log.info("pre_pack: following references after the pack point")
-        # Fill object_ref with references from object states
-        # in transactions that will not be packed.
-        self._fill_nonpacked_refs(conn, cursor, pack_tid, get_references)
+        self.fill_object_refs(conn, cursor, get_references)
 
-        log.debug("pre_pack: populating pack_object")
+        log.info("pre_pack: filling the pack_object table")
         # Fill the pack_object table with OIDs that either will be
         # removed (if nothing references the OID) or whose history will
         # be cut.
@@ -561,7 +560,7 @@
         -- Keep objects that are still referenced by object states in
         -- transactions that will not be packed.
         -- Use temp_pack_visit for temporary state; otherwise MySQL 5 chokes.
-        INSERT INTO temp_pack_visit
+        INSERT INTO temp_pack_visit (zoid)
         SELECT DISTINCT to_zoid
         FROM object_ref
         WHERE tid > %(pack_tid)s;
@@ -583,8 +582,7 @@
         # repeatedly until all references have been satisfied.
         pass_num = 1
         while True:
-            log.info("pre_pack: following references before the pack point, "
-                "pass %d", pass_num)
+            log.info("pre_pack: following references, pass %d", pass_num)
 
             # Make a list of all parent objects that still need
             # to be visited.  Then set pack_object.visited for all pack_object
@@ -592,8 +590,8 @@
             stmt = """
             %(TRUNCATE)s temp_pack_visit;
 
-            INSERT INTO temp_pack_visit (zoid)
-            SELECT zoid
+            INSERT INTO temp_pack_visit (zoid, keep_tid)
+            SELECT zoid, keep_tid
             FROM pack_object
             WHERE keep = %(TRUE)s
                 AND visited = %(FALSE)s;
@@ -621,8 +619,6 @@
             log.debug("pre_pack: checking references from %d object(s)",
                 visit_count)
 
-            self._fill_pack_object_refs(conn, cursor, get_references)
-
             # Visit the children of all parent objects that were
             # just visited.
             stmt = self._scripts['prepack_follow_child_refs']
@@ -638,37 +634,6 @@
                 pass_num += 1
 
 
-    def _fill_nonpacked_refs(self, conn, cursor, pack_tid, get_references):
-        """Fill object_ref for all transactions that will not be packed."""
-        stmt = """
-        SELECT DISTINCT tid
-        FROM object_state
-        WHERE tid > %(pack_tid)s
-            AND NOT EXISTS (
-                SELECT 1
-                FROM object_refs_added
-                WHERE tid = object_state.tid
-            )
-        """
-        self._run_script_stmt(cursor, stmt, {'pack_tid': pack_tid})
-        tids = [tid for (tid,) in cursor]
-        self._add_refs_for_tids(conn, cursor, tids, get_references)
-
-
-    def _fill_pack_object_refs(self, conn, cursor, get_references):
-        """Fill object_ref for all objects that are to be kept."""
-        stmt = """
-        SELECT DISTINCT keep_tid
-        FROM pack_object
-            LEFT JOIN object_refs_added ON (keep_tid = tid)
-        WHERE keep = %(TRUE)s
-            AND object_refs_added.tid IS NULL
-        """
-        self._run_script_stmt(cursor, stmt)
-        tids = [tid for (tid,) in cursor]
-        self._add_refs_for_tids(conn, cursor, tids, get_references)
-
-
     def _add_object_ref_rows(self, cursor, add_rows):
         """Add rows to object_ref.
 
@@ -725,18 +690,29 @@
         return to_count
 
 
-    def _add_refs_for_tids(self, conn, cursor, tids, get_references):
-        """Fill object_refs with all states for multiple transactions."""
+    def fill_object_refs(self, conn, cursor, get_references):
+        """Update the object_refs table by analyzing new transactions."""
+        stmt = """
+        SELECT transaction.tid
+        FROM transaction
+            LEFT JOIN object_refs_added
+                ON (transaction.tid = object_refs_added.tid)
+        WHERE object_refs_added.tid IS NULL
+        """
+        cursor.execute(stmt)
+        tids = [tid for (tid,) in cursor]
         if tids:
             added = 0
-            log.info("pre_pack: discovering references from objects in %d "
+            log.info("discovering references from objects in %d "
                 "transaction(s)" % len(tids))
             for tid in tids:
                 added += self._add_refs_for_tid(cursor, tid, get_references)
-                if added >= 1000:
+                if added >= 10000:
                     # save the work done so far
                     conn.commit()
                     added = 0
+            if added:
+                conn.commit()
 
 
     def _hold_commit_lock(self, cursor):

Modified: relstorage/branches/1.1/relstorage/adapters/mysql.py
===================================================================
--- relstorage/branches/1.1/relstorage/adapters/mysql.py	2009-01-25 06:24:52 UTC (rev 94999)
+++ relstorage/branches/1.1/relstorage/adapters/mysql.py	2009-01-25 06:31:46 UTC (rev 95000)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2008 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -70,7 +70,8 @@
     _scripts.update({
         'create_temp_pack_visit': """
             CREATE TEMPORARY TABLE temp_pack_visit (
-                zoid BIGINT NOT NULL
+                zoid BIGINT NOT NULL,
+                keep_tid BIGINT
             );
             CREATE UNIQUE INDEX temp_pack_visit_zoid ON temp_pack_visit (zoid);
             CREATE TEMPORARY TABLE temp_pack_child (
@@ -87,7 +88,8 @@
             INSERT INTO temp_pack_child
             SELECT DISTINCT to_zoid
             FROM object_ref
-                JOIN temp_pack_visit USING (zoid);
+                JOIN temp_pack_visit USING (zoid)
+            WHERE object_ref.tid >= temp_pack_visit.keep_tid;
 
             -- MySQL-specific syntax for table join in update
             UPDATE pack_object, temp_pack_child SET keep = %(TRUE)s
@@ -203,8 +205,8 @@
         -- the object and all its revisions will be removed.
         -- If keep is true, instead of removing the object,
         -- the pack operation will cut the object's history.
-        -- The keep_tid field specifies which revision to keep within
-        -- the list of packable transactions.
+        -- The keep_tid field specifies the oldest revision
+        -- of the object to keep.
         -- The visited flag is set when pre_pack is visiting an object's
         -- references, and remains set.
         CREATE TABLE pack_object (
@@ -274,6 +276,25 @@
             self.close(conn, cursor)
 
 
+    def drop_all(self):
+        """Drop all tables and sequences."""
+        conn, cursor = self.open()
+        try:
+            try:
+                for tablename in ('pack_state_tid', 'pack_state',
+                        'pack_object', 'object_refs_added', 'object_ref',
+                        'current_object', 'object_state', 'new_oid',
+                        'transaction'):
+                    cursor.execute("DROP TABLE IF EXISTS %s" % tablename)
+            except:
+                conn.rollback()
+                raise
+            else:
+                conn.commit()
+        finally:
+            self.close(conn, cursor)
+
+
     def open(self, transaction_mode="ISOLATION LEVEL READ COMMITTED"):
         """Open a database connection and return (conn, cursor)."""
         try:

Modified: relstorage/branches/1.1/relstorage/adapters/oracle.py
===================================================================
--- relstorage/branches/1.1/relstorage/adapters/oracle.py	2009-01-25 06:24:52 UTC (rev 94999)
+++ relstorage/branches/1.1/relstorage/adapters/oracle.py	2009-01-25 06:31:46 UTC (rev 95000)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2008 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -223,9 +223,10 @@
         -- the object and all its revisions will be removed.
         -- If keep is 'Y', instead of removing the object,
         -- the pack operation will cut the object's history.
-        -- If keep is 'Y' then the keep_tid field must also be set.
-        -- The keep_tid field specifies which revision to keep within
-        -- the list of packable transactions.
+        -- The keep_tid field specifies the oldest revision
+        -- of the object to keep.
+        -- The visited flag is set when pre_pack is visiting an object's
+        -- references, and remains set.
         CREATE TABLE pack_object (
             zoid        NUMBER(20) NOT NULL PRIMARY KEY,
             keep        CHAR NOT NULL CHECK (keep IN ('N', 'Y')),
@@ -250,7 +251,8 @@
         -- Temporary state during packing: a list of objects
         -- whose references need to be examined.
         CREATE GLOBAL TEMPORARY TABLE temp_pack_visit (
-            zoid        NUMBER(20) NOT NULL PRIMARY KEY
+            zoid        NUMBER(20) NOT NULL PRIMARY KEY,
+            keep_tid    NUMBER(20)
         );
 
         -- Temporary state during undo: a list of objects
@@ -311,6 +313,27 @@
             self.close(conn, cursor)
 
 
+    def drop_all(self):
+        """Drop all tables and sequences."""
+        conn, cursor = self.open()
+        try:
+            try:
+                for tablename in ('pack_state_tid', 'pack_state',
+                        'pack_object', 'object_refs_added', 'object_ref',
+                        'current_object', 'object_state', 'transaction',
+                        'commit_lock', 'pack_lock',
+                        'temp_store', 'temp_undo', 'temp_pack_visit'):
+                    cursor.execute("DROP TABLE %s" % tablename)
+                cursor.execute("DROP SEQUENCE zoid_seq")
+            except:
+                conn.rollback()
+                raise
+            else:
+                conn.commit()
+        finally:
+            self.close(conn, cursor)
+
+
     def open(self, transaction_mode="ISOLATION LEVEL READ COMMITTED",
             twophase=False):
         """Open a database connection and return (conn, cursor)."""

Modified: relstorage/branches/1.1/relstorage/adapters/postgresql.py
===================================================================
--- relstorage/branches/1.1/relstorage/adapters/postgresql.py	2009-01-25 06:24:52 UTC (rev 94999)
+++ relstorage/branches/1.1/relstorage/adapters/postgresql.py	2009-01-25 06:31:46 UTC (rev 95000)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2008 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -106,8 +106,8 @@
         -- the object and all its revisions will be removed.
         -- If keep is true, instead of removing the object,
         -- the pack operation will cut the object's history.
-        -- The keep_tid field specifies which revision to keep within
-        -- the list of packable transactions.
+        -- The keep_tid field specifies the oldest revision
+        -- of the object to keep.
         -- The visited flag is set when pre_pack is visiting an object's
         -- references, and remains set.
         CREATE TABLE pack_object (
@@ -186,6 +186,29 @@
             self.close(conn, cursor)
 
 
+    def drop_all(self):
+        """Drop all tables and sequences."""
+        conn, cursor = self.open()
+        try:
+            try:
+                cursor.execute("SELECT tablename FROM pg_tables")
+                existent = set([name for (name,) in cursor])
+                for tablename in ('pack_state_tid', 'pack_state',
+                        'pack_object', 'object_refs_added', 'object_ref',
+                        'current_object', 'object_state', 'transaction',
+                        'commit_lock', 'pack_lock'):
+                    if tablename in existent:
+                        cursor.execute("DROP TABLE %s" % tablename)
+                cursor.execute("DROP SEQUENCE zoid_seq")
+            except:
+                conn.rollback()
+                raise
+            else:
+                conn.commit()
+        finally:
+            self.close(conn, cursor)
+
+
     def open(self,
             isolation=psycopg2.extensions.ISOLATION_LEVEL_READ_COMMITTED):
         """Open a database connection and return (conn, cursor)."""

Modified: relstorage/branches/1.1/relstorage/config.py
===================================================================
--- relstorage/branches/1.1/relstorage/config.py	2009-01-25 06:24:52 UTC (rev 94999)
+++ relstorage/branches/1.1/relstorage/config.py	2009-01-25 06:31:46 UTC (rev 95000)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2008 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,

Modified: relstorage/branches/1.1/relstorage/relstorage.py
===================================================================
--- relstorage/branches/1.1/relstorage/relstorage.py	2009-01-25 06:24:52 UTC (rev 94999)
+++ relstorage/branches/1.1/relstorage/relstorage.py	2009-01-25 06:31:46 UTC (rev 95000)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2008 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -238,7 +238,9 @@
     def _get_oid_cache_key(self, oid_int):
         """Return the cache key for finding the current tid.
 
-        This is overridden by BoundRelStorage.
+        This is overridden by BoundRelStorage.  This version always returns
+        None because a non-bound storage does not have a prev_polled_tid,
+        which is required for cache invalidation.
         """
         return None
 
@@ -261,12 +263,18 @@
         else:
             msg.append("Current transaction is %d" % row[0])
 
-        rows = adapter.iter_object_history(cursor, oid_int)
         tids = []
-        for row in rows:
-            tids.append(row[0])
-            if len(tids) >= 10:
-                break
+        try:
+            rows = adapter.iter_object_history(cursor, oid_int)
+        except KeyError:
+            # The object has no history, at least from the point of view
+            # of the current database load connection.
+            pass
+        else:
+            for row in rows:
+                tids.append(row[0])
+                if len(tids) >= 10:
+                    break
         msg.append("Recent object tids: %s" % repr(tids))
         log.warning('; '.join(msg))
 

Modified: relstorage/branches/1.1/relstorage/tests/alltests.py
===================================================================
--- relstorage/branches/1.1/relstorage/tests/alltests.py	2009-01-25 06:24:52 UTC (rev 94999)
+++ relstorage/branches/1.1/relstorage/tests/alltests.py	2009-01-25 06:31:46 UTC (rev 95000)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2008 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,

Copied: relstorage/branches/1.1/relstorage/tests/fakecache.py (from rev 94998, relstorage/trunk/relstorage/tests/fakecache.py)
===================================================================
--- relstorage/branches/1.1/relstorage/tests/fakecache.py	                        (rev 0)
+++ relstorage/branches/1.1/relstorage/tests/fakecache.py	2009-01-25 06:31:46 UTC (rev 95000)
@@ -0,0 +1,27 @@
+##############################################################################
+#
+# Copyright (c) 2009 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.
+#
+##############################################################################
+"""A memcache-like module sufficient for testing without an actual memcache.
+"""
+
+class Client(object):
+
+    def __init__(self, servers):
+        self.servers = servers
+        self.data = {}
+
+    def get(self, key):
+        return self.data.get(key)
+
+    def set(self, key, value):
+        self.data[key] = value

Modified: relstorage/branches/1.1/relstorage/tests/reltestbase.py
===================================================================
--- relstorage/branches/1.1/relstorage/tests/reltestbase.py	2009-01-25 06:24:52 UTC (rev 94999)
+++ relstorage/branches/1.1/relstorage/tests/reltestbase.py	2009-01-25 06:31:46 UTC (rev 95000)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2008 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -70,6 +70,10 @@
     ReadOnlyStorage.ReadOnlyStorage
     ):
 
+    def checkDropAndPrepare(self):
+        self._storage._adapter.drop_all()
+        self._storage._adapter.prepare_schema()
+
     def checkCrossConnectionInvalidation(self):
         # Verify connections see updated state at txn boundaries
         db = DB(self._storage)
@@ -224,6 +228,33 @@
         self.assertEqual(len(got), len(data))
         self.assertEqual(got, data)
 
+    def checkLoadFromCache(self):
+        # Store an object, cache it, then retrieve it from the cache
+        self._storage._options.cache_servers = 'x:1 y:2'
+        self._storage._options.cache_module_name = 'relstorage.tests.fakecache'
+
+        db = DB(self._storage)
+        try:
+            c1 = db.open()
+            cache = c1._storage._cache_client
+            self.assertEqual(cache.servers, ['x:1', 'y:2'])
+            self.assertEqual(len(cache.data), 0)
+            r1 = c1.root()
+            self.assertEqual(len(cache.data), 2)
+            r1['alpha'] = PersistentMapping()
+            transaction.commit()
+            oid = r1['alpha']._p_oid
+
+            self.assertEqual(len(cache.data), 2)
+            got, serialno = c1._storage.load(oid, '')
+            self.assertEqual(len(cache.data), 4)
+            # load the object from the cache
+            got, serialno = c1._storage.load(oid, '')
+            # try to load an object that doesn't exist
+            self.assertRaises(KeyError, c1._storage.load, 'bad.oid.', '')
+        finally:
+            db.close()
+
     def checkMultipleStores(self):
         # Verify a connection can commit multiple transactions
         db = DB(self._storage)
@@ -248,11 +279,14 @@
             c1.close()
 
             c1._storage._load_conn.close()
+            c1._storage._store_conn.close()
 
             c2 = db.open()
             self.assert_(c2 is c1)
             r = c2.root()
             self.assertEqual(r['alpha'], 1)
+            r['beta'] = 2
+            transaction.commit()
             c2.close()
         finally:
             db.close()
@@ -260,7 +294,7 @@
     def checkPollInterval(self):
         # Verify the poll_interval parameter causes RelStorage to
         # delay invalidation polling.
-        self._storage._poll_interval = 3600
+        self._storage._options.poll_interval = 3600
         db = DB(self._storage)
         try:
             c1 = db.open()
@@ -281,7 +315,10 @@
             storage.tpc_vote(t)
             storage.tpc_finish(t)
 
-            # c2 should not see the change yet
+            # flush invalidations to c2, but the poll timer has not
+            # yet expired, so the change to r2 should not be seen yet.
+            self.assertTrue(c2._storage._poll_at > 0)
+            c2._flush_invalidations()
             r2 = c2.root()
             self.assertEqual(r2['alpha'], 1)
 
@@ -449,7 +486,38 @@
         self._storage._options.pack_gc = False
         self.checkPackGC(gc_enabled=False)
 
+    def checkPackOldUnreferenced(self):
+        db = DB(self._storage)
+        try:
+            c1 = db.open()
+            r1 = c1.root()
+            r1['A'] = PersistentMapping()
+            B = PersistentMapping()
+            r1['A']['B'] = B
+            transaction.get().note('add A then add B to A')
+            transaction.commit()
 
+            del r1['A']['B']
+            transaction.get().note('remove B from A')
+            transaction.commit()
+
+            r1['A']['C'] = ''
+            transaction.get().note('add C to A')
+            transaction.commit()
+
+            now = packtime = time.time()
+            while packtime <= now:
+                packtime = time.time()
+            self._storage.pack(packtime, referencesf)
+
+            # B should be gone, since nothing refers to it.
+            self.assertRaises(KeyError, self._storage.load, B._p_oid, '')
+
+        finally:
+            db.close()
+        
+
+
 class IteratorDeepCompareUnordered:
     # Like IteratorDeepCompare, but compensates for OID order
     # differences in transactions.

Modified: relstorage/branches/1.1/relstorage/tests/speedtest.py
===================================================================
--- relstorage/branches/1.1/relstorage/tests/speedtest.py	2009-01-25 06:24:52 UTC (rev 94999)
+++ relstorage/branches/1.1/relstorage/tests/speedtest.py	2009-01-25 06:31:46 UTC (rev 95000)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2008 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,

Modified: relstorage/branches/1.1/relstorage/tests/testmysql.py
===================================================================
--- relstorage/branches/1.1/relstorage/tests/testmysql.py	2009-01-25 06:24:52 UTC (rev 94999)
+++ relstorage/branches/1.1/relstorage/tests/testmysql.py	2009-01-25 06:31:46 UTC (rev 95000)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2008 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,

Modified: relstorage/branches/1.1/relstorage/tests/testoracle.py
===================================================================
--- relstorage/branches/1.1/relstorage/tests/testoracle.py	2009-01-25 06:24:52 UTC (rev 94999)
+++ relstorage/branches/1.1/relstorage/tests/testoracle.py	2009-01-25 06:31:46 UTC (rev 95000)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2008 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,

Modified: relstorage/branches/1.1/relstorage/tests/testpostgresql.py
===================================================================
--- relstorage/branches/1.1/relstorage/tests/testpostgresql.py	2009-01-25 06:24:52 UTC (rev 94999)
+++ relstorage/branches/1.1/relstorage/tests/testpostgresql.py	2009-01-25 06:31:46 UTC (rev 95000)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2008 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,

Modified: relstorage/branches/1.1/relstorage/zodbconvert.py
===================================================================
--- relstorage/branches/1.1/relstorage/zodbconvert.py	2009-01-25 06:24:52 UTC (rev 94999)
+++ relstorage/branches/1.1/relstorage/zodbconvert.py	2009-01-25 06:31:46 UTC (rev 95000)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 ##############################################################################
 #
-# Copyright (c) 2008 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,

Modified: relstorage/branches/1.1/setup.py
===================================================================
--- relstorage/branches/1.1/setup.py	2009-01-25 06:24:52 UTC (rev 94999)
+++ relstorage/branches/1.1/setup.py	2009-01-25 06:31:46 UTC (rev 95000)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2008 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Foundation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,



More information about the Checkins mailing list