Howard Chu writes:
h.b.furuseth@usit.uio.no wrote:
If a cursor is at a clean subDB page, and its current item is deleted by another cursor, then MDB_GET_CURRENT returns the deleted item.
Fixed now in mdb.master. The subcursor on the clean page will be invalidated when the page is touched.
MDB_NEXT/MDB_PREV crash on assert(mc->mc_flags & C_INITIALIZED) since commit e31c7d3b31d8d5073195e31b283e8ccb46bd13cf, with the patch below to the test program.
One partial fix: Instead return a new error code MDB_BAD_CURSOR or maybe MDB_UNSPECIFIED. Also make mdb_cursor_<next/prev>() less forgiving of errors, otherwise the user gets different success results for the two cursors again. Branch mdb/its7594 in http://folk.uio.no/hbf/OpenLDAP/openldap.git does this. I did not look at how to get the cursors return the same result.
mdb.master output with patched test program:
With clean page: Name: Key -> Data (mv_data[mv_len]): m2: a[2] -> x[2] mc/del: a[2] -> [0] a.out: mdb.c:4386: mdb_cursor_next: Assertion `mc->mc_flags & 0x01' failed.
Branch mdb/its7594 output:
With clean page: Name: Key -> Data (mv_data[mv_len]): m2: a[2] -> x[2] mc/del: a[2] -> [0] its7594a.c:48: mdb_cursor_get(m2, &key, &data, MDB_NEXT): MDB_BAD_CURSOR: Cursor is unusable
That assert is OK since it's the test program asserting success.
--- its7594.c +++ its7594a.c @@ -28,4 +28,6 @@ E(mdb_cursor_put(mc, STR2VAL("a"), STR2VAL("x"), 0)); E(mdb_cursor_put(mc, STR2VAL("a"), STR2VAL("y"), 0)); + E(mdb_cursor_put(mc, STR2VAL("b"), STR2VAL("z"), 0)); + E(mdb_cursor_put(mc, STR2VAL("c"), STR2VAL("w"), 0));
if (argc < 2) { @@ -42,8 +44,8 @@
E(mdb_cursor_del(mc, 0)); - E(mdb_cursor_get(m2, &key, &data, MDB_GET_CURRENT)); - SHOW("m2/del"); /* Should output the same as... */ - E(mdb_cursor_get(mc, &key, &data, MDB_GET_CURRENT)); - SHOW("mc/del"); /* ...this: "a[2] -> [0]". */ + E(mdb_cursor_get(mc, &key, &data, MDB_NEXT)); + SHOW("mc/del"); /* Outputs "a[2] -> [0]"... */ + E(mdb_cursor_get(m2, &key, &data, MDB_NEXT)); + SHOW("m2/del"); /* ...and this should output the same. */
mdb_txn_abort(txn);