Skip to content

Commit 7e3c532

Browse files
committed
ITS#8263 fix cursor tracking in cursor_put
1 parent 9ed1e57 commit 7e3c532

File tree

1 file changed

+63
-14
lines changed

1 file changed

+63
-14
lines changed

libraries/liblmdb/mdb.c

Lines changed: 63 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,7 @@ static int mdb_cursor_last(MDB_cursor *mc, MDB_val *key, MDB_val *data);
12421242
static void mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx);
12431243
static void mdb_xcursor_init0(MDB_cursor *mc);
12441244
static void mdb_xcursor_init1(MDB_cursor *mc, MDB_node *node);
1245+
static void mdb_xcursor_init2(MDB_cursor *mc, MDB_node *node);
12451246

12461247
static int mdb_drop0(MDB_cursor *mc, int subs);
12471248
static void mdb_default_cmp(MDB_txn *txn, MDB_dbi dbi);
@@ -6554,23 +6555,23 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
65546555
rc = mdb_cursor_put(&mc->mc_xcursor->mx_cursor, &dkey, &xdata, xflags);
65556556
if (rc)
65566557
goto bad_sub;
6557-
{
6558-
/* Adjust other cursors pointing to mp */
6559-
MDB_cursor *m2;
6560-
unsigned i = mc->mc_top;
6561-
MDB_page *mp = mc->mc_pg[i];
6562-
6563-
for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2=m2->mc_next) {
6564-
if (m2 == mc || m2->mc_snum < mc->mc_snum) continue;
6565-
if (!(m2->mc_flags & C_INITIALIZED)) continue;
6566-
if (m2->mc_pg[i] == mp && m2->mc_ki[i] == mc->mc_ki[i]) {
6567-
mdb_xcursor_init1(m2, leaf);
6568-
}
6569-
}
6570-
}
65716558
/* we've done our job */
65726559
dkey.mv_size = 0;
65736560
}
6561+
{
6562+
/* Adjust other cursors pointing to mp */
6563+
MDB_cursor *m2;
6564+
unsigned i = mc->mc_top;
6565+
MDB_page *mp = mc->mc_pg[i];
6566+
6567+
for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2=m2->mc_next) {
6568+
if (m2 == mc || m2->mc_snum < mc->mc_snum) continue;
6569+
if (!(m2->mc_flags & C_INITIALIZED)) continue;
6570+
if (m2->mc_pg[i] == mp && m2->mc_ki[i] == mc->mc_ki[i]) {
6571+
mdb_xcursor_init2(m2, leaf);
6572+
}
6573+
}
6574+
}
65746575
ecount = mc->mc_xcursor->mx_db.md_entries;
65756576
if (flags & MDB_APPENDDUP)
65766577
xflags |= MDB_APPEND;
@@ -7122,6 +7123,54 @@ mdb_xcursor_init1(MDB_cursor *mc, MDB_node *node)
71227123
#endif
71237124
}
71247125

7126+
7127+
/** Fixup a sorted-dups cursor due to underlying update.
7128+
* Sets up some fields that depend on the data from the main cursor.
7129+
* Almost the same as init1, but skips initialization steps if the
7130+
* xcursor had already been used.
7131+
* @param[in] mc The main cursor whose sorted-dups cursor is to be fixed up.
7132+
* @param[in] node The data containing the #MDB_db record for the
7133+
* sorted-dup database.
7134+
*/
7135+
static void
7136+
mdb_xcursor_init2(MDB_cursor *mc, MDB_node *node)
7137+
{
7138+
MDB_xcursor *mx = mc->mc_xcursor;
7139+
7140+
if (node->mn_flags & F_SUBDATA) {
7141+
memcpy(&mx->mx_db, NODEDATA(node), sizeof(MDB_db));
7142+
mdb_page_get(mc->mc_txn,mx->mx_db.md_root,&mx->mx_cursor.mc_pg[0],NULL);
7143+
} else {
7144+
MDB_page *fp = NODEDATA(node);
7145+
mx->mx_db.md_entries = NUMKEYS(fp);
7146+
COPY_PGNO(mx->mx_db.md_root, fp->mp_pgno);
7147+
mx->mx_cursor.mc_pg[0] = fp;
7148+
}
7149+
if (!(mx->mx_cursor.mc_flags & C_INITIALIZED)) {
7150+
mx->mx_cursor.mc_snum = 1;
7151+
mx->mx_cursor.mc_top = 0;
7152+
mx->mx_cursor.mc_flags |= C_INITIALIZED;
7153+
mx->mx_cursor.mc_ki[0] = 0;
7154+
if (!(node->mn_flags & F_SUBDATA)) {
7155+
mx->mx_db.md_pad = 0;
7156+
mx->mx_db.md_flags = 0;
7157+
mx->mx_db.md_depth = 1;
7158+
mx->mx_db.md_branch_pages = 0;
7159+
mx->mx_db.md_leaf_pages = 1;
7160+
mx->mx_db.md_overflow_pages = 0;
7161+
if (mc->mc_db->md_flags & MDB_DUPFIXED) {
7162+
mx->mx_db.md_flags = MDB_DUPFIXED;
7163+
mx->mx_db.md_pad = mx->mx_cursor.mc_pg[0]->mp_pad;
7164+
if (mc->mc_db->md_flags & MDB_INTEGERDUP)
7165+
mx->mx_db.md_flags |= MDB_INTEGERKEY;
7166+
}
7167+
}
7168+
}
7169+
DPRINTF(("Sub-db -%u root page %"Z"u", mx->mx_cursor.mc_dbi,
7170+
mx->mx_db.md_root));
7171+
mx->mx_dbflag = DB_VALID|DB_USRVALID|DB_DIRTY; /* DB_DIRTY guides mdb_cursor_touch */
7172+
}
7173+
71257174
/** Initialize a cursor for a given transaction and database. */
71267175
static void
71277176
mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx)

0 commit comments

Comments
 (0)