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

Re: (ITS#7594) incomplete MDB subdb cursor cleanup



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);

-- 
Hallvard