Skip to content

Commit

Permalink
zodbcommit: Robustify copy handling
Browse files Browse the repository at this point in the history
When zodbdump input says to copy an object, we first load that object.
However if object does not exist loadBefore raises POSKeyError, and when
object at copied-from revision was deleted loadBefore returns None.

-> Handle that explicitly to provide failure details to the user, so
that instead of cryptic

    === RUN   TestLoad/δstart=0285cbac75555580
    Traceback (most recent call last):
      File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
        "__main__", fname, loader, pkg_name)
      File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
        exec code in run_globals
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodb.py", line 133, in <module>
        main()
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodb.py", line 129, in main
        return command_module.main(argv)
      File "<decorator-gen-6>", line 2, in main
      File "/home/kirr/src/tools/go/pygolang/golang/__init__.py", line 103, in _
        return f(*argv, **kw)
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodbrestore.py", line 94, in main
        zodbrestore(stor, asbinstream(sys.stdin), _)
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodbrestore.py", line 43, in zodbrestore
        zodbcommit(stor, at, txn)
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodbcommit.py", line 122, in zodbcommit
        _()
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodbcommit.py", line 91, in _
        data, _, _ = stor.loadBefore(obj.oid, p64(u64(obj.copy_from)+1))
    TypeError: 'NoneType' object is not iterable
        xtesting.go:483: /tmp/demo009767458/δ0285cbac75555580/δ.fs: zpyrestore: exit status 1

it fails with something more understandable:

    === RUN   TestLoad/δstart=0285cbac75555580
    Traceback (most recent call last):
      File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
        "__main__", fname, loader, pkg_name)
      File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
        exec code in run_globals
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodb.py", line 133, in <module>
        main()
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodb.py", line 129, in main
        return command_module.main(argv)
      File "<decorator-gen-6>", line 2, in main
      File "/home/kirr/src/tools/go/pygolang/golang/__init__.py", line 103, in _
        return f(*argv, **kw)
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodbrestore.py", line 94, in main
        zodbrestore(stor, asbinstream(sys.stdin), _)
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodbrestore.py", line 43, in zodbrestore
        zodbcommit(stor, at, txn)
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodbcommit.py", line 129, in zodbcommit
        _()
      File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodbcommit.py", line 97, in _
        (stor.getName(), ashex(obj.oid), ashex(obj.copy_from)))
    ValueError: /tmp/demo358030847/δ0285cbac75555580/δ.fs: object 0000000000000003: copy from @0285cbac70a3d733: no data
        xtesting.go:483: /tmp/demo358030847/δ0285cbac75555580/δ.fs: zpyrestore: exit status 1

For the implementation it would be easier to use loadAt
(zopefoundation/ZODB#323), but we don't have
that yet.

/reviewed-by @jerome
/reviewed-on https://lab.nexedi.com/nexedi/zodbtools/merge_requests/20
  • Loading branch information
navytux committed Mar 16, 2021
1 parent 4275f2e commit fa00c28
Showing 1 changed file with 8 additions and 1 deletion.
9 changes: 8 additions & 1 deletion zodbtools/zodbcommit.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,14 @@ def current_serial(oid):
copy_from = None
if isinstance(obj, zodbdump.ObjectCopy):
copy_from = obj.copy_from
data, _, _ = stor.loadBefore(obj.oid, p64(u64(obj.copy_from)+1))
try:
xdata = stor.loadBefore(obj.oid, p64(u64(obj.copy_from)+1))
except POSKeyError:
xdata = None
if xdata is None:
raise ValueError("%s: object %s: copy from @%s: no data" %
(stor.getName(), ashex(obj.oid), ashex(obj.copy_from)))
data, _, _ = xdata

elif isinstance(obj, zodbdump.ObjectDelete):
data = None
Expand Down

0 comments on commit fa00c28

Please sign in to comment.