Commit 8fdb3f34 authored by Shane Hathaway's avatar Shane Hathaway

Improved documentation of the refresh-related functionality.

- Renamed updateCodeTimestamp() to resetCaches().

- Added a test of resetCaches().

- Removed a spurious comment about chaining connections together.
parent 3aa9bcf5
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
############################################################################## ##############################################################################
"""Database connection support """Database connection support
$Id: Connection.py,v 1.103 2003/12/08 21:12:25 jeremy Exp $""" $Id: Connection.py,v 1.104 2003/12/10 20:02:15 shane Exp $"""
import sys import sys
import threading import threading
...@@ -33,16 +33,20 @@ from ZODB.utils import oid_repr, z64 ...@@ -33,16 +33,20 @@ from ZODB.utils import oid_repr, z64
from ZODB.serialize \ from ZODB.serialize \
import ObjectWriter, getClassMetadata, ConnectionObjectReader import ObjectWriter, getClassMetadata, ConnectionObjectReader
global_code_timestamp = 0 global_reset_counter = 0
def updateCodeTimestamp(): def resetCaches():
"""Called after changes are made to persistence-based classes. """Causes all connection caches to be reset as connections are reopened.
Causes all connection caches to be re-created as the connections are Zope's refresh feature uses this. When you reload Python modules,
reopened. instances of classes continue to use the old class definitions.
To use the new code immediately, the refresh feature asks ZODB to
clear caches by calling resetCaches(). When the instances are
loaded by subsequent connections, they will use the new class
definitions.
""" """
global global_code_timestamp global global_reset_counter
global_code_timestamp = time() global_reset_counter += 1
class Connection(ExportImport, object): class Connection(ExportImport, object):
"""Object managers for individual object space. """Object managers for individual object space.
...@@ -55,12 +59,9 @@ class Connection(ExportImport, object): ...@@ -55,12 +59,9 @@ class Connection(ExportImport, object):
_tmp=None _tmp=None
_debug_info=() _debug_info=()
_opened=None _opened=None
_code_timestamp = 0 _reset_counter = 0
_transaction = None _transaction = None
# Experimental. Other connections can register to be closed
# when we close by putting something here.
def __init__(self, version='', cache_size=400, def __init__(self, version='', cache_size=400,
cache_deactivate_after=60): cache_deactivate_after=60):
"""Create a new Connection""" """Create a new Connection"""
...@@ -76,7 +77,7 @@ class Connection(ExportImport, object): ...@@ -76,7 +77,7 @@ class Connection(ExportImport, object):
self._cache.cache_drain_resistance = 100 self._cache.cache_drain_resistance = 100
self._incrgc = self.cacheGC = cache.incrgc self._incrgc = self.cacheGC = cache.incrgc
self._committed = [] self._committed = []
self._code_timestamp = global_code_timestamp self._reset_counter = global_reset_counter
self._load_count = 0 # Number of objects unghosted self._load_count = 0 # Number of objects unghosted
self._store_count = 0 # Number of objects stored self._store_count = 0 # Number of objects stored
...@@ -161,7 +162,7 @@ class Connection(ExportImport, object): ...@@ -161,7 +162,7 @@ class Connection(ExportImport, object):
self._storage = odb._storage self._storage = odb._storage
self._sortKey = odb._storage.sortKey self._sortKey = odb._storage.sortKey
self.new_oid = odb._storage.new_oid self.new_oid = odb._storage.new_oid
if self._code_timestamp != global_code_timestamp: if self._reset_counter != global_reset_counter:
# New code is in place. Start a new cache. # New code is in place. Start a new cache.
self._resetCache() self._resetCache()
else: else:
...@@ -173,8 +174,11 @@ class Connection(ExportImport, object): ...@@ -173,8 +174,11 @@ class Connection(ExportImport, object):
return self return self
def _resetCache(self): def _resetCache(self):
"""Creates a new cache, discarding the old.""" """Creates a new cache, discarding the old.
self._code_timestamp = global_code_timestamp
See the docstring for the resetCaches() function.
"""
self._reset_counter = global_reset_counter
self._invalidated.clear() self._invalidated.clear()
cache_size = self._cache.cache_size cache_size = self._cache.cache_size
self._cache = cache = PickleCache(self, cache_size) self._cache = cache = PickleCache(self, cache_size)
......
...@@ -139,6 +139,9 @@ class ZODBTests(unittest.TestCase): ...@@ -139,6 +139,9 @@ class ZODBTests(unittest.TestCase):
def checkResetCache(self): def checkResetCache(self):
# The cache size after a reset should be 0 and the GC attributes # The cache size after a reset should be 0 and the GC attributes
# ought to be linked to it rather than the old cache. # ought to be linked to it rather than the old cache.
# Note that _resetCache is not a public API, but the
# resetCaches() function is, and resetCaches() causes
# _resetCache() to be called.
self.populate() self.populate()
conn = self._db.open() conn = self._db.open()
conn.root() conn.root()
...@@ -148,6 +151,19 @@ class ZODBTests(unittest.TestCase): ...@@ -148,6 +151,19 @@ class ZODBTests(unittest.TestCase):
self.assert_(conn._incrgc == conn._cache.incrgc) self.assert_(conn._incrgc == conn._cache.incrgc)
self.assert_(conn.cacheGC == conn._cache.incrgc) self.assert_(conn.cacheGC == conn._cache.incrgc)
def checkResetCachesAPI(self):
# Checks the resetCaches() API.
# (resetCaches used to be called updateCodeTimestamp.)
self.populate()
conn = self._db.open()
conn.root()
self.assert_(len(conn._cache) > 0) # Precondition
ZODB.Connection.resetCaches()
conn.close()
self.assert_(len(conn._cache) > 0) # Still not flushed
conn._setDB(self._db) # simulate the connection being reopened
self.assertEqual(len(conn._cache), 0)
def checkLocalTransactions(self): def checkLocalTransactions(self):
# Test of transactions that apply to only the connection, # Test of transactions that apply to only the connection,
# not the thread. # not the thread.
...@@ -282,3 +298,7 @@ class ZODBTests(unittest.TestCase): ...@@ -282,3 +298,7 @@ class ZODBTests(unittest.TestCase):
def test_suite(): def test_suite():
return unittest.makeSuite(ZODBTests, 'check') return unittest.makeSuite(ZODBTests, 'check')
if __name__ == "__main__":
unittest.main(defaultTest="test_suite")
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment