On 03/01/17 22:04, lazarev.michael(a)gmail.com wrote:
After a number of mdb_put calls, mdb_cursor_get with MDB_LAST
positions the cursor incorrectly. Test code is submitted here:
The C_EOF flag is doubly broken here, and maybe ill-defined:
Previous mdb_cursor_last() set C_EOF as a "cursor is on the last page"
hint, cursor_put() did not clear it in this cursor when putting
through another cursor, and then next cursor_last() uses the hint in
"if (!(mc->mc_flags & C_EOF))" when the cursor is no longer at the end.
However, elsewhere the flag is seen as "cursor is beyond last item":
mdb_cursor_next(), MDB_GET_MULTIPLE, mdb_cursor_count(). It is set
that way after mdb_cursor_sibling(<right>) fails. But it's not used
consistently that way either: At least MDB_GET_CURRENT, MDB_PREV,
put(MDB_CURRENT) succeed with C_EOF set. (And they don't move
the cursor to the last item first.)
As for the "cursor is on last page" hint, page_search() & co could at
least avoid some page_get()s without using C_EOF: If C_INITIALIZED is
set, then while mc_pg and mc_ki are correct it can just walk
down the cursor without doing page_get(). If a _pg or _ki needs to
change, it can switch to the regular page_seaarch() code. Helps
write-txns and MDB_VL32, but not read-only txns.