Commit e30c3f37 authored by Jim Fulton's avatar Jim Fulton

Removed a somewhat nonsensical backward-compatibility test.

Changed the behavior for closing changes when changes weren't passed
in. When no changes are passed to the constructor, then they are
closed when the storage is closed.

Fixed a test that wasn't testing what it though it was (or anything really).
parent 987b67d4
...@@ -39,7 +39,7 @@ class DemoStorage(object): ...@@ -39,7 +39,7 @@ class DemoStorage(object):
) )
def __init__(self, name=None, base=None, changes=None, def __init__(self, name=None, base=None, changes=None,
close_base_on_close=None, close_changes_on_close=None): close_base_on_close=None, close_changes_on_close=True):
if close_base_on_close is None: if close_base_on_close is None:
if base is None: if base is None:
...@@ -56,13 +56,9 @@ class DemoStorage(object): ...@@ -56,13 +56,9 @@ class DemoStorage(object):
self._temporary_changes = True self._temporary_changes = True
changes = ZODB.MappingStorage.MappingStorage() changes = ZODB.MappingStorage.MappingStorage()
zope.interface.alsoProvides(self, ZODB.interfaces.IBlobStorage) zope.interface.alsoProvides(self, ZODB.interfaces.IBlobStorage)
if close_changes_on_close is None:
close_changes_on_close = False
else: else:
if ZODB.interfaces.IBlobStorage.providedBy(changes): if ZODB.interfaces.IBlobStorage.providedBy(changes):
zope.interface.alsoProvides(self, ZODB.interfaces.IBlobStorage) zope.interface.alsoProvides(self, ZODB.interfaces.IBlobStorage)
if close_changes_on_close is None:
close_changes_on_close = True
self.changes = changes self.changes = changes
self.close_changes_on_close = close_changes_on_close self.close_changes_on_close = close_changes_on_close
...@@ -81,11 +77,12 @@ class DemoStorage(object): ...@@ -81,11 +77,12 @@ class DemoStorage(object):
self._next_oid = random.randint(1, 1<<62) self._next_oid = random.randint(1, 1<<62)
__temporary_blobdir = None
def _blobify(self): def _blobify(self):
if (self._temporary_changes and if (self._temporary_changes and
isinstance(self.changes, ZODB.MappingStorage.MappingStorage) isinstance(self.changes, ZODB.MappingStorage.MappingStorage)
): ):
blob_dir = tempfile.mkdtemp('.demoblobs') blob_dir = self.__temporary_blobdir = tempfile.mkdtemp('.demoblobs')
_temporary_blobdirs[ _temporary_blobdirs[
weakref.ref(self, cleanup_temporary_blobdir) weakref.ref(self, cleanup_temporary_blobdir)
] = blob_dir ] = blob_dir
...@@ -102,6 +99,9 @@ class DemoStorage(object): ...@@ -102,6 +99,9 @@ class DemoStorage(object):
self.base.close() self.base.close()
if self.close_changes_on_close: if self.close_changes_on_close:
self.changes.close() self.changes.close()
if (self.__temporary_blobdir and
os.path.exists(self.__temporary_blobdir)):
ZODB.blob.remove_committed_dir(self.__temporary_blobdir)
def _copy_methods_from_changes(self, changes): def _copy_methods_from_changes(self, changes):
for meth in ( for meth in (
......
...@@ -185,30 +185,6 @@ The pop method closes the changes storage and returns the base ...@@ -185,30 +185,6 @@ The pop method closes the changes storage and returns the base
>>> changes.opened() >>> changes.opened()
False False
Special backward compatibility support
--------------------------------------
Normally, when a demo storage is closed, it's base and changes
storage are closed.
Older versions of DemoStorage didn't have a separate changes storage
and didn't close or discard their changes when they were closed. When
a stack was built solely of demo storages, the close method
effectively did nothing. To maintain backward compatibility, when no
base or changes storage is supplied in the constructor, the underlying
storage created by the demo storage isn't closed by the demo storage.
This backward-compatibility is deprecated.
>>> demo = DemoStorage()
>>> demo.close()
>>> demo.changes.opened(), demo.base.opened()
(True, True)
>>> demo = DemoStorage(base=MappingStorage())
>>> demo2 = demo.push()
>>> demo2.close()
>>> demo2.changes.opened(), demo2.base.base.opened()
(True, False)
Blob Support Blob Support
============ ============
...@@ -355,32 +331,70 @@ and base options: ...@@ -355,32 +331,70 @@ and base options:
>>> storage.base.getName() >>> storage.base.getName()
'base.fs' 'base.fs'
>>> storage.close()
Generating OIDs Generating OIDs
=============== ===============
When asked for a new OID DemoStorage randomly chooses a value and then verifies When asked for a new OID DemoStorage chooses a value and then
that neither the base or changes storages already contain that OID. verifies that neither the base or changes storages already contain
that OID. It chooses values sequentially from random starting
points, picking new starting points whenever a chosen value us already
in the changes or base.
Under rare circumstances an OID can be chosen that has already been handed out, Under rare circumstances an OID can be chosen that has already been
but which hasn't yet been comitted. Lets verify that if the same OID is chosen handed out, but which hasn't yet been comitted. Lets verify that if
twice during a transaction that everything will still work. the same OID is chosen twice during a transaction that everything will
still work.
First we'll get a single OID. To test this, we need to hack random.randint a bit.
>>> import random >>> import random
>>> storage = DemoStorage.push(storage) >>> randint = random.randint
>>> random.seed(47)
>>> storage.new_oid() >>> rv = 42
'8\xaa-\tz\x1dP\x07' >>> def faux_randint(min, max):
... print 'called randint'
... global rv
... rv += 1000
... return rv
>>> random.randint = faux_randint
Now, we create a demostorage.
>>> storage = DemoStorage()
called randint
Then we'll force the random number generator to use the same seed for the If we ask for an oid, we'll get 1042.
subsequent call to "new_oid" and show that we get a different OID.
>>> random.seed(47) >>> u64(storage.new_oid())
1042
oids are allocated seuentially:
>>> u64(storage.new_oid())
1043
Now, we'll save 1044 in changes so that it has to pick a new one randomly.
>>> t = transaction.get()
>>> ZODB.tests.util.store(storage.changes, 1044)
>>> u64(storage.new_oid())
called randint
2042
Now, we hack rv to 1042 is given out again and we'll save 2043 in base
to force another attempt:
>>> rv -= 1000
>>> ZODB.tests.util.store(storage.changes, 2043)
>>> oid = storage.new_oid() >>> oid = storage.new_oid()
>>> oid called randint
'8\xaa-\tz\x1dP\x08' called randint
>>> u64(oid)
3042
DemoStorage keeps up with the issued OIDs to know when not to reissue them... DemoStorage keeps up with the issued OIDs to know when not to reissue them...
...@@ -389,27 +403,20 @@ DemoStorage keeps up with the issued OIDs to know when not to reissue them... ...@@ -389,27 +403,20 @@ DemoStorage keeps up with the issued OIDs to know when not to reissue them...
...but once data is stored with a given OID... ...but once data is stored with a given OID...
>>> t = transaction.begin() >>> ZODB.tests.util.store(storage, oid)
>>> storage.tpc_begin(t)
>>> tid = storage.store(oid, 0, 'data', '', t)
>>> storage.tpc_vote(t)
>>> oid in storage._issued_oids
True
>>> storage.tpc_finish(t)
...there's no need to remember it any longer: ...there's no need to remember it any longer:
>>> oid in storage._issued_oids >>> oid in storage._issued_oids
False False
We're done with the storage, so "unwrap" the underlying storage. >>> storage.close()
.. restore randint
>>> storage = storage.pop() >>> random.randint = randint
.. restore time .. restore time
>>> time.time = real_time_time >>> time.time = real_time_time
.. clean up
>>> storage.close()
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