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