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. 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; }