h.b.furuseth@usit.uio.no wrote:
Changes from a failed liblmdb operation can be visible. Sometimes the resulting DB will also be inconsistent. The operation should invalidate the affected transaction/cursors or revert the change.
The transaction should be invalidated. Nothing more can be done once any error occurs in a transaction.
At least I hope it's feasible to invalidate so the user cannot see surprising results, instead of just documenting "don't do that".
Related issues:
put(MDB_MULTIPLE) can write some of the provided items and then fail, but be able to keep the txn usable. It should invalidate the txn anyway, or document that the caller must check for e.g. return value MDB_PARTIAL_SUCCESS. Maybe invalidate unless the the caller requests support for partial success. put() would update the input params to indicate which items remain unwritten.
No, "partial success" is not allowed. A transaction is atomic, all or nothing.
A failed txn could still grow the txn size, unless MDB "un-touches" pages which memcmp says have not changed, rewinds me_pglast and me_pghead, etc. Which seems a lot of work, likely not worth the trouble.
pghead/pglast should not persist into the environment until a successful commit. Until then any error should just discard them.
I think cursors need a C_INVALID flag, so future ops cannot give a surprising success result instead of failing: get(MDB_NEXT/MDB_PREV) take ~C_INITIALIZED to mean (re)start from the beginning/end.
Good idea.
Don't know how often reverting is a relevant option. Rearranging code can help, but maybe not much. E.g. the mdb_del() in mdb_drop() can do some harmless touches and then fail cleanly - but mdb_drop() must invalidate the txn anyway since mdb_drop0() has deleted pages. Unless it does extra work - remember mt_free_pgs[0] before and after mdb_drop0(), then delete from mt_free_pgs[] the pages added by drop0. Or drop0 could be done last since it can fail cleanly just by resetting mt_free_pgs[0]. But I don't know if del(MDB_MULTIPLE) can also do that if the DB used a subpage. drop0 can't examine the subpage after it got deleted.
Reverting is irrelevant. Once a txn is aborted no changes are visible.