• Kirill Smelkov's avatar
    DemoStorage: Add support for deleteObject (IExternalGC) · 49f5959e
    Kirill Smelkov authored
    So that it is generally possible to zodbrestore[1,2] zodbdumped[3]
    database/transactions into DemoStorage. Because without this patch, when dump
    contains deletion records, e.g.
    
        txn 0285cbacc06d3a4c " "
        user ""
        description ""
        extension ""
        obj 0000000000000007 delete
    
    it fails like this:
    
        Traceback (most recent call last):
          ...
          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 131, in zodbcommit
            _()
          File "/home/kirr/src/wendelin/z/zodbtools/zodbtools/zodbcommit.py", line 118, in _
            stor.deleteObject(obj.oid, current_serial(obj.oid), txn)
        AttributeError: 'DemoStorage' object has no attribute 'deleteObject'
            demo_test.go:105: demo:(file:///tmp/demo470143633/δ0285cbac258bf266/base.fs)/(file:///tmp/demo470143633/δ0285cbac258bf266/δ.fs): zpyrestore: exit status 1
    
    To be able to implement DemoStorage.deleteObject, we have to fix
    FileStorage.deleteObject first: currently FileStorage.deleteObject raises
    POSKeyError if an object is not present in the database, but for situation
    where
    
    - demo=base+δ,
    - object is present in base, and
    - object is not present in δ
    
    it creates a problem because there is no way to add whiteout record for the
    object into δ.
    
    This change should be generally good; let me quote
    neo@543041a3 for why:
    
    ---- 8< ----
    Even though currently it is not possible to create such data record via
    FileStorage(py).deleteObject (because it raises POSKeyError if there is
    no previous object revision), being able to use such data records is
    semantically useful in overlayed DemoStorage settings, where δ part
    marks an object that exists only in base with delete record whiteout.
    
    It is also generally meaningful to be able to create "delete" record
    even if object was not previously existing: "deleteObject" is actually
    similar to "store" (and so should be better named as "storeDelete"). If
    one wants to store deletion, there should not be a reason to reject it,
    because deleteObject already has seatbelt in the form of oldserial, and
    if the user calls deleteObject(oid, oldserial=z64), he/she is already
    telling that "I know that this object does not exist in this storage
    (oldserial=z64), but still please create a deletion record for it". Once
    again this is useful in overlayed DemoStorage settings described above.
    
    For the reference, such whiteout deletion records pass ZODB/scripts/fstest just fine.
    ---- 8< ----
    
    DemoStorage.deleteObject implementation is straightforward, but builds on
    loadAt[4] as precondition.
    
    /cc @jimfulton, @jamadden, @perrinjerome
    
    [1] https://lab.nexedi.com/nexedi/zodbtools/blob/129afa67/zodbtools/zodbrestore.py
    [2] nexedi/zodbtools!19
    [3] https://lab.nexedi.com/nexedi/zodbtools/blob/129afa67/zodbtools/zodbdump.py
    [4] https://github.com/zopefoundation/ZODB/pull/323
    49f5959e
testDemoStorage.py 12.3 KB