[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: (ITS#8557) mdb_put may cause a cursor malfunction



On 03/01/17 22:04, lazarev.michael@gmail.com wrote:
> After a number of mdb_put calls, mdb_cursor_get with MDB_LAST operation
> positions the cursor incorrectly. Test code is submitted here:
> ftp://ftp.openldap.org/incoming/mdb_put_test.c

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.