Commit b7d618b4 authored by Jim Fulton's avatar Jim Fulton

Bug Fixed:

"Blob temp file get's removed before it should",
https://bugs.launchpad.net/zodb/+bug/595378

A way this to happen is that a transaction is aborted after the
commit process has started. I don't know how this would happen in
the wild.

In 3.10.3, the ZEO tpc_abort call to the server is changed to be
synchronous, which should address this case. Maybe there's another
case.
parent 1995cf9f
......@@ -13,6 +13,18 @@ Bugs Fixed
https://bugs.launchpad.net/zodb/+bug/737198
- "Blob temp file get's removed before it should",
https://bugs.launchpad.net/zodb/+bug/595378
A way this to happen is that a transaction is aborted after the
commit process has started. I don't know how this would happen in
the wild.
In 3.10.3, the ZEO tpc_abort call to the server is changed to be
synchronous, which should address this case. Maybe there's another
case.
Performance enhancements
------------------------
......
......@@ -252,7 +252,7 @@ class StorageServer:
return self.rpc.call('tpc_finish', id)
def tpc_abort(self, id):
self.rpc.callAsync('tpc_abort', id)
self.rpc.call('tpc_abort', id)
def history(self, oid, length=None):
if length is None:
......
......@@ -1498,6 +1498,44 @@ def unix_domain_sockets():
>>> c.root.x = 1
>>> transaction.commit()
>>> c.close()
"""
def gracefully_handle_abort_while_storing_many_blobs():
r"""
>>> import logging, sys
>>> old_level = logging.getLogger().getEffectiveLevel()
>>> logging.getLogger().setLevel(logging.ERROR)
>>> handler = logging.StreamHandler(sys.stdout)
>>> logging.getLogger().addHandler(handler)
>>> addr, _ = start_server(port='./sock', blob_dir='blobs')
>>> c = ZEO.connection(addr, blob_dir='cblobs')
>>> c.root.x = ZODB.blob.Blob('z'*(1<<20))
>>> c.root.y = ZODB.blob.Blob('z'*(1<<2))
>>> t = c.transaction_manager.get()
>>> c.tpc_begin(t)
>>> c.commit(t)
We've called commit, but the blob sends are queued. We'll call abort
right away, which will delete the temporary blob files. The queued
iterators will try to open these files.
>>> c.tpc_abort(t)
Now we'll try to use the connection, mainly to wait for everything to
get processed. Before we fixed this by making tpc_finish a synchronous
call to the server. we'd get some sort of error here.
>>> _ = c._storage._server.loadEx('\0'*8)
>>> c.close()
>>> logging.getLogger().removeHandler(handler)
>>> logging.getLogger().setLevel(old_level)
"""
if sys.platform.startswith('win'):
......
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