From 5f6fa8c04204888c4ff7ac6be1868d81ff4410a8 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Tue, 3 Sep 2013 16:10:20 -0700 Subject: [PATCH] Remember if last cursor op was a delete If so, don't advance cursor on next NEXT. Also, init xcursor on the next GET_CURRENT. --- libraries/liblmdb/mdb.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index f59fe51..dc20b4f 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -933,6 +933,7 @@ struct MDB_cursor { #define C_INITIALIZED 0x01 /**< cursor has been initialized and is valid */ #define C_EOF 0x02 /**< No more data */ #define C_SUB 0x04 /**< Cursor is a sub-cursor */ +#define C_DEL 0x08 /**< last op was a cursor_del */ #define C_SPLITTING 0x20 /**< Cursor is in page_split */ #define C_UNTRACK 0x40 /**< Un-track cursor when closing */ /** @} */ @@ -5006,6 +5007,8 @@ mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op) } DPRINTF(("cursor_next: top page is %"Z"u in cursor %p", mp->mp_pgno, (void *) mc)); + if (mc->mc_flags & C_DEL) + goto skip; if (mc->mc_ki[mc->mc_top] + 1u >= NUMKEYS(mp)) { DPUTS("=====> move to next sibling page"); @@ -5018,6 +5021,7 @@ mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op) } else mc->mc_ki[mc->mc_top]++; +skip: DPRINTF(("==> cursor points to page %"Z"u with %u keys, key index %u", mp->mp_pgno, NUMKEYS(mp), mc->mc_ki[mc->mc_top])); @@ -5432,6 +5436,8 @@ mdb_cursor_get(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_GET_KEY(leaf, key); if (data) { if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + if (mc->mc_flags & C_DEL) + mdb_xcursor_init1(mc, leaf); rc = mdb_cursor_get(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_GET_CURRENT); } else { rc = mdb_node_read(mc->mc_txn, leaf, data); @@ -5556,6 +5562,9 @@ fetchm: break; } + if (mc->mc_flags & C_DEL) + mc->mc_flags ^= C_DEL; + return rc; } @@ -6105,6 +6114,7 @@ mdb_cursor_del(MDB_cursor *mc, unsigned int flags) } } mc->mc_db->md_entries--; + mc->mc_flags |= C_DEL; return rc; } /* otherwise fall thru and delete the sub-DB */ @@ -7280,12 +7290,16 @@ mdb_cursor_del0(MDB_cursor *mc, MDB_node *leaf) if (!(m2->mc_flags & C_INITIALIZED)) continue; if (m2->mc_pg[mc->mc_top] == mp) { - if (m2->mc_ki[mc->mc_top] > ki) - m2->mc_ki[mc->mc_top]--; + if (m2->mc_ki[mc->mc_top] >= ki) { + m2->mc_flags |= C_DEL; + if (m2->mc_ki[mc->mc_top] > ki) + m2->mc_ki[mc->mc_top]--; + } if (m2->mc_ki[mc->mc_top] >= nkeys) mdb_cursor_sibling(m2, 1); } } + mc->mc_flags |= C_DEL; } return rc;