Howard Chu writes:
> h.b.furuseth(a)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.
That would break back-mdb for MDB_NOTFOUND/MDB_KEYEXIST. And at
least MDB_KEYEXIST can happen after touching pages, which affects
the txn size even if the change "does nothing".
I expected to generally invalidate except in necessary cases, and
from then on make more cases "gentle" at our convenience without
spending much time on it.
>> put(MDB_MULTIPLE) can write some of the provided items and then
>> fail, but be able to keep the txn usable. (...)
>
> No, "partial success" is not allowed. A transaction is atomic, all
> or nothing.
It would be atomic like a partial OS write(). It'd be up to the
user what to do next. Not that I care myself if it is supported.
>> 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.
Sorry, I meant a failed _operation_ could grow them and thus affect
the committed freelist size.
>> 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.
...or C_VALID so a single OR/AND can set/clear them both.
>> Don't know how often reverting is a relevant option. (...)
>
> Reverting is irrelevant. Once a txn is aborted no changes are visible.
True, but I meant while the txn is still live and usable. Hopefully
it's only relevant for "nice to have" cases.
--
Hallvard