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

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



h.b.furuseth@usit.uio.no wrote:
> Full_Name: Hallvard B Furuseth
> Version: mdb.master 0cdd9dffddf66c730a35f48db2bb02d8bb3e5731
> OS: Linux x86_64
> URL:
> Submission from: (NULL) (193.69.163.163)
> Submitted by: hallvard
>
>
> 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.

> Test program below, run with no args, the "m2/del" output line.
>
> If the page was dirty, I instead got (key = old, data = size 0).
> I don't know if it should give MDB_NOTFOUND instead.
> That's the test program run with one arg.
> I did not check what happens if the other cursor rearranged
> the pages, e.g. split the item off to another page.
>
> #include "lmdb.h"
> #include <assert.h>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main(int argc, char **argv)
> {
>      char *fname = "test.mdb";
>      MDB_env *env;
>      MDB_txn *txn;
>      MDB_dbi dbi;
>      MDB_cursor *mc, *m2;
>      MDB_val key, data;
>      int rc;
> #   define STR2VAL(s) (&(MDB_val){sizeof(s), s}) /* includes final \0 */
> #   define SHOW(name) printf("%s:\t%s[%zd] -> %s[%zd]\n", name, \
>          (char*)key.mv_data, key.mv_size, (char*)data.mv_data, data.mv_size)
> #   define E(e) { rc = (e); if (rc) { fprintf(stderr, "%s:%d: %s: %s\n",\
>          __FILE__, __LINE__, #e, mdb_strerror(rc)); abort(); } }
>
>      remove(fname);
>      E(mdb_env_create(&env));
>      E(mdb_env_open(env, fname, MDB_NOSUBDIR, 0666));
>      E(mdb_txn_begin(env, NULL, 0, &txn));
>      E(mdb_dbi_open(txn, NULL, MDB_DUPSORT, &dbi));
>
>      E(mdb_cursor_open(txn, dbi, &mc));
>      E(mdb_cursor_put(mc, STR2VAL("a"), STR2VAL("x"), 0));
>      E(mdb_cursor_put(mc, STR2VAL("a"), STR2VAL("y"), 0));
>
>      if (argc < 2) {
>          E(mdb_txn_commit(txn));
>          E(mdb_txn_begin(env, NULL, 0, &txn));
>          E(mdb_cursor_open(txn, dbi, &mc));
>          puts("With clean page:");
>      }
>      E(mdb_cursor_open(txn, dbi, &m2));
>
>      E(mdb_cursor_get(mc, &key, &data, MDB_FIRST));
>      E(mdb_cursor_get(m2, &key, &data, MDB_FIRST));
>      SHOW("Name:\tKey  -> Data  (mv_data[mv_len]):\n"  "m2");
>
>      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]". */
>
>      mdb_txn_abort(txn);
>      mdb_env_close(env);
>      return 0;
> }
>
>


-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/