[Checkins] SVN: ZODB/trunk/src/ZEO/ Changed the dropped-cache event to a StaleCache event that's published

Jim Fulton jim at zope.com
Tue Nov 18 21:30:18 EST 2008


Log message for revision 93124:
  Changed the dropped-cache event to a StaleCache event that's published
  whenever the cache is stale. This is generated before dropping a cache
  and starting cold so that an application can take more drastic
  measures. The stale-cache event also now has a storage attribute with
  the storage that has a stale cache.
  

Changed:
  U   ZODB/trunk/src/ZEO/ClientStorage.py
  U   ZODB/trunk/src/ZEO/interfaces.py
  U   ZODB/trunk/src/ZEO/tests/drop_cache_rather_than_verify.txt

-=-
Modified: ZODB/trunk/src/ZEO/ClientStorage.py
===================================================================
--- ZODB/trunk/src/ZEO/ClientStorage.py	2008-11-19 02:15:37 UTC (rev 93123)
+++ ZODB/trunk/src/ZEO/ClientStorage.py	2008-11-19 02:30:17 UTC (rev 93124)
@@ -1254,6 +1254,8 @@
         elif ltid and ltid != utils.z64:
             self._cache.setLastTid(ltid)
 
+        zope.event.notify(ZEO.interfaces.StaleCache(self))
+
         # From this point on, we do not have complete information about
         # the missed transactions.  The reason is that cache
         # verification only checks objects in the client cache and
@@ -1265,7 +1267,6 @@
 
         if self._cache and self._drop_cache_rather_verify:
             logger.critical("%s dropping stale cache", self.__name__)
-            zope.event.notify(ZEO.interfaces.CacheDroppedEvent())
             self._cache.clear()
             if ltid:
                 self._cache.setLastTid(ltid)

Modified: ZODB/trunk/src/ZEO/interfaces.py
===================================================================
--- ZODB/trunk/src/ZEO/interfaces.py	2008-11-19 02:15:37 UTC (rev 93123)
+++ ZODB/trunk/src/ZEO/interfaces.py	2008-11-19 02:30:17 UTC (rev 93124)
@@ -14,10 +14,13 @@
 
 import zope.interface
 
-class CacheDroppedEvent(object):
-    """A ZEO Cache file was dropped to avoid verification 
+class StaleCache(object):
+    """A ZEO cache is stale and requires verification. 
     """
 
+    def __init__(self, storage):
+        self.storage = storage
+
 class IServeable(zope.interface.Interface):
     """Interface provided by storages that can be served by ZEO
     """

Modified: ZODB/trunk/src/ZEO/tests/drop_cache_rather_than_verify.txt
===================================================================
--- ZODB/trunk/src/ZEO/tests/drop_cache_rather_than_verify.txt	2008-11-19 02:15:37 UTC (rev 93123)
+++ ZODB/trunk/src/ZEO/tests/drop_cache_rather_than_verify.txt	2008-11-19 02:30:17 UTC (rev 93124)
@@ -6,9 +6,13 @@
 might be necessary, but cache verification can be very hard on the
 storage server.
 
+When verification is needed, a ZEO.interfaces.StaleCache event is
+published. Applications may handle this event to perform actions such
+as exiting the process to avoid a cold restart.
+
 ClientStorage provides an option to drop it's cache rather than doing
 verification.  When this option is used, and verification would be
-necessary, ClientStorage:
+necessary, after publishing the event, ClientStorage:
 
 - Invalidates all object caches
 
@@ -17,8 +21,6 @@
 
 - Logs a CRITICAL message.
 
-- Publishes a ZEO.interfaces.CacheDroppedEvent event.
-
 Here's an example that shows that this is actually what happens.
 
 Start a server, create a cient to it and commit some data
@@ -58,8 +60,15 @@
     >>> handler = zope.testing.loggingsupport.InstalledHandler(
     ...     'ZEO.ClientStorage', level=logging.ERROR)
     >>> events = []
-    >>> zope.event.subscribers.append(events.append)
+    >>> def event_handler(e):
+    ...     events.append((
+    ...       len(e.storage._cache), str(handler), e.__class__.__name__))
+    >>> zope.event.subscribers.append(event_handler)
 
+Note that the event handler is saving away the length of the cache and
+the state of the log handler.  We'll use this to show that the event
+is generated before the cache is dropped or the message is logged.
+
 Now, we'll restart the server on the original address:
 
     >>> _, admin = start_server(zeo_conf=dict(invalidation_queue_size=1),
@@ -67,6 +76,19 @@
     >>> wait_connected(db.storage)
 
 Now, let's verify our assertions above:
+
+- Publishes a stale-cache event.
+
+    >>> for e in events:
+    ...     print e
+    (3, '', 'StaleCache')
+
+    Note that the length of the cache when the event handler was
+    called waa non-zero.  This is because the cache wasn't cleared
+    yet.  Similarly, the dropping-cache message hasn't been logged
+    yet.
+
+    >>> del events[:]
   
 - Drops or clears it's client cache. (The end result is that the cache
   is working but empty.)
@@ -87,14 +109,6 @@
 
     >>> handler.clear()
 
-- Publishes a cache-dropped event.
-
-    >>> for e in events:
-    ...     print e.__class__.__name__
-    CacheDroppedEvent
-
-    >>> del events[:]
-
 If we access the root object, it'll be loaded from the server:
 
     >>> conn.root()[1].x
@@ -130,6 +144,14 @@
 (When a database is created, it checks to make sure the root object is
 in the database, which is why we get 1, rather than 0 objects in the cache.)
 
+- Publishes a stake-cache event.
+
+    >>> for e in events:
+    ...     print e
+    (2, '', 'StaleCache')
+
+    >>> del events[:]
+
 - Logs a CRITICAL message.
 
     >>> print handler
@@ -138,16 +160,57 @@
 
     >>> handler.clear()
 
-- Publishes a cache-dropped event.
+If we access the root object, it'll be loaded from the server:
 
-    >>> for e in events:
-    ...     print e.__class__.__name__
-    CacheDroppedEvent
+    >>> conn = db.open()
+    >>> conn.root()[1].x
+    11
 
-If we access the root object, it'll be loaded from the server:
 
+Finally, let's look at what happens without the
+drop_cache_rather_verify option:
+
+    >>> db.close()
+    >>> db = ZEO.DB(addr, client='cache')
+    >>> wait_connected(db.storage)
     >>> conn = db.open()
     >>> conn.root()[1].x
     11
+    >>> conn.root()[2] = conn.root().__class__()
+    >>> transaction.commit()
+    >>> len(db.storage._cache)
+    4
 
+    >>> stop_server(admin)
+    >>> addr2, admin = start_server(keep=1)
+    >>> db2 = ZEO.DB(addr2)
+    >>> wait_connected(db2.storage)
+    >>> conn2 = db2.open()
+    >>> for i in range(5):
+    ...     conn2.root()[1].x += 1
+    ...     transaction.commit()
+    >>> db2.close()
+    >>> stop_server(admin)
+
+    >>> _, admin = start_server(zeo_conf=dict(invalidation_queue_size=1),
+    ...                         addr=addr)
+    >>> wait_connected(db.storage)
+
+    >>> for e in events:
+    ...     print e
+    (4, '', 'StaleCache')
+
+    >>> print handler
+    <BLANKLINE>
+
+    >>> len(db.storage._cache)
+    3
+
+Here we see the cache wasn't dropped, although one of the records was
+invalidated during verification.
+
+.. Cleanup
+
     >>> db.close()
+    >>> handler.uninstall()
+    >>> zope.event.subscribers.remove(event_handler)



More information about the Checkins mailing list