mdbx: Merge branch 'devel' into master.

This commit is contained in:
Leo Yuriev 2015-11-26 14:03:22 +03:00
commit 28caf0dde5
3 changed files with 116 additions and 47 deletions

10
CHANGES
View File

@ -20,6 +20,7 @@ LMDB 0.9.17 Release Engineering
Fix ITS#8312 loose pages in nested txn Fix ITS#8312 loose pages in nested txn
Fix ITS#8313 mdb_rebalance dummy cursor Fix ITS#8313 mdb_rebalance dummy cursor
Fix ITS#8315 dirty_room in nested txn Fix ITS#8315 dirty_room in nested txn
Fix ITS#8323 dirty_list in nested txn
Fix ITS#8316 page_merge cursor tracking Fix ITS#8316 page_merge cursor tracking
Fix ITS#8319 mdb_load error messages Fix ITS#8319 mdb_load error messages
Fix ITS#8320 mdb_load plaintext input Fix ITS#8320 mdb_load plaintext input
@ -29,9 +30,12 @@ LMDB 0.9.17 Release Engineering
Miscellaneous cleanup/simplification Miscellaneous cleanup/simplification
Build Build
Create install dirs if needed (ITS#8256) Create install dirs if needed (ITS#8256)
Fix ThreadProc decl on Win32/MSVC (ITS#8270) Fix ThreadProc decl on Win32/MSVC (ITS#8270 - nothing for MDBX)
Added ssize_t typedef for MSVC (ITS#8067) Added ssize_t typedef for MSVC (ITS#8067 - nothing for MDBX)
Use ANSI apis on Windows (ITS#8069) Use ANSI apis on Windows (ITS#8069 - nothing for MDBX)
Use O_SYNC if O_DSYNC,MDB_DSYNC are not defined (ITS#7209 - nothing for MDBX)
Allow passing AR to make (ITS#8168 - already done for MDBX)
Allow passing mandir to make install (ITS#8169)
LMDB 0.9.16 Release (2015/08/14) LMDB 0.9.16 Release (2015/08/14)
Fix cursor EOF bug (ITS#8190) Fix cursor EOF bug (ITS#8190)

View File

@ -18,6 +18,7 @@ XCFLAGS ?=
CFLAGS ?= -O2 -g -Wall -Werror -Wno-unused-parameter CFLAGS ?= -O2 -g -Wall -Werror -Wno-unused-parameter
CFLAGS += -pthread $(XCFLAGS) CFLAGS += -pthread $(XCFLAGS)
prefix ?= /usr/local prefix ?= /usr/local
mandir ?= $(prefix)/man
######################################################################## ########################################################################
@ -46,7 +47,7 @@ install: $(ILIBS) $(IPROGS) $(IHDRS)
for f in $(IPROGS); do cp $$f $(DESTDIR)$(prefix)/bin; done for f in $(IPROGS); do cp $$f $(DESTDIR)$(prefix)/bin; done
for f in $(ILIBS); do cp $$f $(DESTDIR)$(prefix)/lib; done for f in $(ILIBS); do cp $$f $(DESTDIR)$(prefix)/lib; done
for f in $(IHDRS); do cp $$f $(DESTDIR)$(prefix)/include; done for f in $(IHDRS); do cp $$f $(DESTDIR)$(prefix)/include; done
for f in $(IDOCS); do cp $$f $(DESTDIR)$(prefix)/man/man1; done for f in $(IDOCS); do cp $$f $(DESTDIR)$(mandir)/man1; done
clean: clean:
rm -rf $(PROGS) @* *.[ao] *.[ls]o *~ testdb/* *.gcov rm -rf $(PROGS) @* *.[ao] *.[ls]o *~ testdb/* *.gcov

150
mdb.c
View File

@ -1409,6 +1409,13 @@ mdb_cursor_chk(MDB_cursor *mc)
} }
if (unlikely(mc->mc_ki[i] >= NUMKEYS(mc->mc_pg[i]))) if (unlikely(mc->mc_ki[i] >= NUMKEYS(mc->mc_pg[i])))
mdb_print("ack!\n"); mdb_print("ack!\n");
if (mc->mc_xcursor && (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)) {
node = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
if (((node->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA) &&
mc->mc_xcursor->mx_cursor.mc_pg[0] != NODEDATA(node)) {
mdb_print("blah!\n");
}
}
} }
#endif /* 0 */ #endif /* 0 */
@ -2497,14 +2504,15 @@ done:
} else { } else {
for (; m2; m2=m2->mc_next) { for (; m2; m2=m2->mc_next) {
if (m2->mc_snum < mc->mc_snum) continue; if (m2->mc_snum < mc->mc_snum) continue;
if (m2 == mc) continue;
if (m2->mc_pg[mc->mc_top] == mp) { if (m2->mc_pg[mc->mc_top] == mp) {
m2->mc_pg[mc->mc_top] = np; m2->mc_pg[mc->mc_top] = np;
if ((mc->mc_db->md_flags & MDB_DUPSORT) && if ((mc->mc_db->md_flags & MDB_DUPSORT) &&
IS_LEAF(np) && IS_LEAF(np) &&
m2->mc_ki[mc->mc_top] == mc->mc_ki[mc->mc_top]) (m2->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED))
{ {
MDB_node *leaf = NODEPTR(np, mc->mc_ki[mc->mc_top]); MDB_node *leaf = NODEPTR(np, m2->mc_ki[mc->mc_top]);
if (!(leaf->mn_flags & F_SUBDATA)) if ((leaf->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA)
m2->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf); m2->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf);
} }
} }
@ -3761,6 +3769,25 @@ mdb_txn_commit(MDB_txn *txn)
pspill[0] = y; pspill[0] = y;
} }
/* Remove anything in our spill list from parent's dirty list */
if (txn->mt_spill_pgs && txn->mt_spill_pgs[0]) {
for (i=1; i<=txn->mt_spill_pgs[0]; i++) {
MDB_ID pn = txn->mt_spill_pgs[i];
if (pn & 1)
continue; /* deleted spillpg */
pn >>= 1;
y = mdb_mid2l_search(dst, pn);
if (y <= dst[0].mid && dst[y].mid == pn) {
free(dst[y].mptr);
while (y < dst[0].mid) {
dst[y] = dst[y+1];
y++;
}
dst[0].mid--;
}
}
}
/* Find len = length of merging our dirty list with parent's */ /* Find len = length of merging our dirty list with parent's */
x = dst[0].mid; x = dst[0].mid;
dst[0].mid = 0; /* simplify loops */ dst[0].mid = 0; /* simplify loops */
@ -5247,8 +5274,11 @@ mdb_cursor_pop(MDB_cursor *mc)
mc->mc_pg[mc->mc_top]->mp_pgno, DDBI(mc), (void *) mc); mc->mc_pg[mc->mc_top]->mp_pgno, DDBI(mc), (void *) mc);
mc->mc_snum--; mc->mc_snum--;
if (mc->mc_snum) if (mc->mc_snum) {
mc->mc_top--; mc->mc_top--;
} else {
mc->mc_flags &= ~C_INITIALIZED;
}
} }
} }
@ -5972,6 +6002,8 @@ mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data,
} else } else
return MDB_NOTFOUND; return MDB_NOTFOUND;
} }
} else {
mc->mc_pg[0] = 0;
} }
rc = mdb_page_search(mc, key, 0); rc = mdb_page_search(mc, key, 0);
@ -6186,8 +6218,6 @@ mdb_cursor_get(MDB_cursor *mc, MDB_val *key, MDB_val *data,
MDB_GET_KEY(leaf, key); MDB_GET_KEY(leaf, key);
if (data) { if (data) {
if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { 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); rc = mdb_cursor_get(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_GET_CURRENT);
} else { } else {
rc = mdb_node_read(mc->mc_txn, leaf, data); rc = mdb_node_read(mc->mc_txn, leaf, data);
@ -6778,7 +6808,7 @@ new_sub:
} else { } else {
/* There is room already in this leaf page. */ /* There is room already in this leaf page. */
rc = mdb_node_add(mc, mc->mc_ki[mc->mc_top], key, rdata, 0, nflags); rc = mdb_node_add(mc, mc->mc_ki[mc->mc_top], key, rdata, 0, nflags);
if (likely(rc == 0) && insert_key) { if (likely(rc == 0)) {
/* Adjust other cursors pointing to mp */ /* Adjust other cursors pointing to mp */
MDB_cursor *m2, *m3; MDB_cursor *m2, *m3;
MDB_dbi dbi = mc->mc_dbi; MDB_dbi dbi = mc->mc_dbi;
@ -6790,10 +6820,15 @@ new_sub:
m3 = &m2->mc_xcursor->mx_cursor; m3 = &m2->mc_xcursor->mx_cursor;
else else
m3 = m2; m3 = m2;
if (m3 == mc || m3->mc_snum < mc->mc_snum) continue; if (m3 == mc || m3->mc_snum < mc->mc_snum || m3->mc_pg[i] != mp) continue;
if (m3->mc_pg[i] == mp && m3->mc_ki[i] >= mc->mc_ki[i]) { if (m3->mc_ki[i] >= mc->mc_ki[i] && insert_key) {
m3->mc_ki[i]++; m3->mc_ki[i]++;
} }
if (m3->mc_xcursor && (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)) {
MDB_node *n2 = NODEPTR(mp, m3->mc_ki[i]);
if ((n2->mn_flags & (F_SUBDATA|F_DUPDATA)) == F_DUPDATA)
m3->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(n2);
}
} }
} }
} }
@ -6932,6 +6967,7 @@ mdb_cursor_del(MDB_cursor *mc, unsigned flags)
if (flags & MDB_NODUPDATA) { if (flags & MDB_NODUPDATA) {
/* mdb_cursor_del0() will subtract the final entry */ /* mdb_cursor_del0() will subtract the final entry */
mc->mc_db->md_entries -= mc->mc_xcursor->mx_db.md_entries - 1; mc->mc_db->md_entries -= mc->mc_xcursor->mx_db.md_entries - 1;
mc->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED;
} else { } else {
if (!F_ISSET(leaf->mn_flags, F_SUBDATA)) { if (!F_ISSET(leaf->mn_flags, F_SUBDATA)) {
mc->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf); mc->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf);
@ -6967,8 +7003,9 @@ mdb_cursor_del(MDB_cursor *mc, unsigned flags)
} }
} }
mc->mc_db->md_entries--; mc->mc_db->md_entries--;
mc->mc_flags |= C_DEL;
return rc; return rc;
} else {
mc->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED;
} }
/* otherwise fall thru and delete the sub-DB */ /* otherwise fall thru and delete the sub-DB */
} }
@ -7679,21 +7716,21 @@ mdb_update_key(MDB_cursor *mc, MDB_val *key)
static void static void
mdb_cursor_copy(const MDB_cursor *csrc, MDB_cursor *cdst); mdb_cursor_copy(const MDB_cursor *csrc, MDB_cursor *cdst);
/** Track a temporary cursor */ /** Perform \b act while tracking temporary cursor \b mn */
#define CURSOR_TMP_TRACK(mc, mn, dummy, tracked) \ #define WITH_CURSOR_TRACKING(mn, act) do { \
if (mc->mc_flags & C_SUB) { \ MDB_cursor dummy, *tracked, **tp = &(mn).mc_txn->mt_cursors[mn.mc_dbi]; \
if ((mn).mc_flags & C_SUB) { \
dummy.mc_flags = C_INITIALIZED; \ dummy.mc_flags = C_INITIALIZED; \
dummy.mc_xcursor = (MDB_xcursor *)&mn; \ dummy.mc_xcursor = (MDB_xcursor *)&(mn); \
tracked = &dummy; \ tracked = &dummy; \
} else { \ } else { \
tracked = &mn; \ tracked = &(mn); \
} \ } \
tracked->mc_next = mc->mc_txn->mt_cursors[mc->mc_dbi]; \ tracked->mc_next = *tp; \
mc->mc_txn->mt_cursors[mc->mc_dbi] = tracked *tp = tracked; \
{ act; } \
/** Stop tracking a temporary cursor */ *tp = tracked->mc_next; \
#define CURSOR_TMP_UNTRACK(mc, tracked) \ } while (0)
mc->mc_txn->mt_cursors[mc->mc_dbi] = tracked->mc_next
/** Move a node from csrc to cdst. /** Move a node from csrc to cdst.
*/ */
@ -7750,6 +7787,7 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft)
data.mv_size = NODEDSZ(srcnode); data.mv_size = NODEDSZ(srcnode);
data.mv_data = NODEDATA(srcnode); data.mv_data = NODEDATA(srcnode);
} }
mn.mc_xcursor = NULL;
if (IS_BRANCH(cdst->mc_pg[cdst->mc_top]) && cdst->mc_ki[cdst->mc_top] == 0) { if (IS_BRANCH(cdst->mc_pg[cdst->mc_top]) && cdst->mc_ki[cdst->mc_top] == 0) {
unsigned snum = cdst->mc_snum; unsigned snum = cdst->mc_snum;
MDB_node *s2; MDB_node *s2;
@ -7821,6 +7859,12 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft)
m3->mc_ki[csrc->mc_top] = cdst->mc_ki[cdst->mc_top]; m3->mc_ki[csrc->mc_top] = cdst->mc_ki[cdst->mc_top];
m3->mc_ki[csrc->mc_top-1]++; m3->mc_ki[csrc->mc_top-1]++;
} }
if (m3->mc_xcursor && (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) &&
IS_LEAF(mps)) {
MDB_node *node = NODEPTR(m3->mc_pg[csrc->mc_top], m3->mc_ki[csrc->mc_top]);
if ((node->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA)
m3->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(node);
}
} }
} else } else
/* Adding on the right, bump others down */ /* Adding on the right, bump others down */
@ -7841,6 +7885,12 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft)
} else { } else {
m3->mc_ki[csrc->mc_top]--; m3->mc_ki[csrc->mc_top]--;
} }
if (m3->mc_xcursor && (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) &&
IS_LEAF(mps)) {
MDB_node *node = NODEPTR(m3->mc_pg[csrc->mc_top], m3->mc_ki[csrc->mc_top]);
if ((node->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA)
m3->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(node);
}
} }
} }
} }
@ -7850,7 +7900,6 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft)
*/ */
if (csrc->mc_ki[csrc->mc_top] == 0) { if (csrc->mc_ki[csrc->mc_top] == 0) {
if (csrc->mc_ki[csrc->mc_top-1] != 0) { if (csrc->mc_ki[csrc->mc_top-1] != 0) {
MDB_cursor dummy, *tracked;
if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) { if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.mv_size); key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.mv_size);
} else { } else {
@ -7864,9 +7913,7 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft)
mn.mc_snum--; mn.mc_snum--;
mn.mc_top--; mn.mc_top--;
/* We want mdb_rebalance to find mn when doing fixups */ /* We want mdb_rebalance to find mn when doing fixups */
CURSOR_TMP_TRACK(csrc, mn, dummy, tracked); WITH_CURSOR_TRACKING(mn, rc = mdb_update_key(&mn, &key));
rc = mdb_update_key(&mn, &key);
CURSOR_TMP_UNTRACK(csrc, tracked);
if (unlikely(rc != MDB_SUCCESS)) if (unlikely(rc != MDB_SUCCESS))
return rc; return rc;
} }
@ -7883,7 +7930,6 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft)
if (cdst->mc_ki[cdst->mc_top] == 0) { if (cdst->mc_ki[cdst->mc_top] == 0) {
if (cdst->mc_ki[cdst->mc_top-1] != 0) { if (cdst->mc_ki[cdst->mc_top-1] != 0) {
MDB_cursor dummy, *tracked;
if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) { if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
key.mv_data = LEAF2KEY(cdst->mc_pg[cdst->mc_top], 0, key.mv_size); key.mv_data = LEAF2KEY(cdst->mc_pg[cdst->mc_top], 0, key.mv_size);
} else { } else {
@ -7897,9 +7943,7 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft)
mn.mc_snum--; mn.mc_snum--;
mn.mc_top--; mn.mc_top--;
/* We want mdb_rebalance to find mn when doing fixups */ /* We want mdb_rebalance to find mn when doing fixups */
CURSOR_TMP_TRACK(cdst, mn, dummy, tracked); WITH_CURSOR_TRACKING(mn, rc = mdb_update_key(&mn, &key));
rc = mdb_update_key(&mn, &key);
CURSOR_TMP_UNTRACK(cdst, tracked);
if (unlikely(rc != MDB_SUCCESS)) if (unlikely(rc != MDB_SUCCESS))
return rc; return rc;
} }
@ -7969,6 +8013,7 @@ mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
MDB_cursor mn; MDB_cursor mn;
MDB_node *s2; MDB_node *s2;
mdb_cursor_copy(csrc, &mn); mdb_cursor_copy(csrc, &mn);
mn.mc_xcursor = NULL;
/* must find the lowest key below src */ /* must find the lowest key below src */
rc = mdb_page_search_lowest(&mn); rc = mdb_page_search_lowest(&mn);
if (unlikely(rc)) if (unlikely(rc))
@ -8044,6 +8089,12 @@ mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
m3->mc_ki[top-1] > csrc->mc_ki[top-1]) { m3->mc_ki[top-1] > csrc->mc_ki[top-1]) {
m3->mc_ki[top-1]--; m3->mc_ki[top-1]--;
} }
if (m3->mc_xcursor && (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) &&
IS_LEAF(psrc)) {
MDB_node *node = NODEPTR(m3->mc_pg[top], m3->mc_ki[top]);
if ((node->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA)
m3->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(node);
}
} }
} }
{ {
@ -8258,13 +8309,11 @@ mdb_rebalance(MDB_cursor *mc)
if (!fromleft) { if (!fromleft) {
rc = mdb_page_merge(&mn, mc); rc = mdb_page_merge(&mn, mc);
} else { } else {
MDB_cursor dummy, *tracked;
oldki += NUMKEYS(mn.mc_pg[mn.mc_top]); oldki += NUMKEYS(mn.mc_pg[mn.mc_top]);
mn.mc_ki[mn.mc_top] += mc->mc_ki[mn.mc_top] + 1; mn.mc_ki[mn.mc_top] += mc->mc_ki[mn.mc_top] + 1;
/* We want mdb_rebalance to find mn when doing fixups */ /* We want mdb_rebalance to find mn when doing fixups */
CURSOR_TMP_TRACK(mc, mn, dummy, tracked); WITH_CURSOR_TRACKING(mn,
rc = mdb_page_merge(mc, &mn); rc = mdb_page_merge(mc, &mn));
CURSOR_TMP_UNTRACK(mc, tracked);
mdb_cursor_copy(&mn, mc); mdb_cursor_copy(&mn, mc);
} }
mc->mc_flags &= ~C_EOF; mc->mc_flags &= ~C_EOF;
@ -8297,12 +8346,17 @@ mdb_cursor_del0(MDB_cursor *mc)
if (m3 == mc || m3->mc_snum < mc->mc_snum) if (m3 == mc || m3->mc_snum < mc->mc_snum)
continue; continue;
if (m3->mc_pg[mc->mc_top] == mp) { if (m3->mc_pg[mc->mc_top] == mp) {
if (m3->mc_ki[mc->mc_top] >= ki) { if (m3->mc_ki[mc->mc_top] == ki) {
m3->mc_flags |= C_DEL; m3->mc_flags |= C_DEL;
if (m3->mc_ki[mc->mc_top] > ki) if (mc->mc_db->md_flags & MDB_DUPSORT)
m3->mc_ki[mc->mc_top]--;
else if (mc->mc_db->md_flags & MDB_DUPSORT)
m3->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED; m3->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED;
} else if (m3->mc_ki[mc->mc_top] > ki) {
m3->mc_ki[mc->mc_top]--;
}
if (m3->mc_xcursor && (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)) {
MDB_node *node = NODEPTR(m3->mc_pg[mc->mc_top], m3->mc_ki[mc->mc_top]);
if ((node->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA)
m3->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(node);
} }
} }
} }
@ -8492,6 +8546,7 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
} }
mdb_cursor_copy(mc, &mn); mdb_cursor_copy(mc, &mn);
mn.mc_xcursor = NULL;
mn.mc_pg[mn.mc_top] = rp; mn.mc_pg[mn.mc_top] = rp;
mn.mc_ki[ptop] = mc->mc_ki[ptop]+1; mn.mc_ki[ptop] = mc->mc_ki[ptop]+1;
@ -8634,14 +8689,11 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
*/ */
if (SIZELEFT(mn.mc_pg[ptop]) < mdb_branch_size(env, &sepkey)) { if (SIZELEFT(mn.mc_pg[ptop]) < mdb_branch_size(env, &sepkey)) {
int snum = mc->mc_snum; int snum = mc->mc_snum;
MDB_cursor dummy, *tracked;
mn.mc_snum--; mn.mc_snum--;
mn.mc_top--; mn.mc_top--;
did_split = 1; did_split = 1;
/* We want other splits to find mn when doing fixups */ /* We want other splits to find mn when doing fixups */
CURSOR_TMP_TRACK(mc, mn, dummy, tracked); WITH_CURSOR_TRACKING(mn, rc = mdb_page_split(&mn, &sepkey, NULL, rp->mp_pgno, 0));
rc = mdb_page_split(&mn, &sepkey, NULL, rp->mp_pgno, 0);
CURSOR_TMP_UNTRACK(mc, tracked);
if (unlikely(rc != MDB_SUCCESS)) if (unlikely(rc != MDB_SUCCESS))
goto done; goto done;
@ -8799,7 +8851,7 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
m3->mc_ki[k+1] = m3->mc_ki[k]; m3->mc_ki[k+1] = m3->mc_ki[k];
m3->mc_pg[k+1] = m3->mc_pg[k]; m3->mc_pg[k+1] = m3->mc_pg[k];
} }
if (m3->mc_ki[0] > nkeys) { if (m3->mc_ki[0] >= nkeys) {
m3->mc_ki[0] = 1; m3->mc_ki[0] = 1;
} else { } else {
m3->mc_ki[0] = 0; m3->mc_ki[0] = 0;
@ -8823,6 +8875,12 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
m3->mc_ki[ptop] >= mc->mc_ki[ptop]) { m3->mc_ki[ptop] >= mc->mc_ki[ptop]) {
m3->mc_ki[ptop]++; m3->mc_ki[ptop]++;
} }
if (m3->mc_xcursor && (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) &&
IS_LEAF(mp)) {
MDB_node *node = NODEPTR(m3->mc_pg[mc->mc_top], m3->mc_ki[mc->mc_top]);
if ((node->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA)
m3->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(node);
}
} }
} }
mdb_debug("mp left: %d, rp left: %d", SIZELEFT(mp), SIZELEFT(rp)); mdb_debug("mp left: %d, rp left: %d", SIZELEFT(mp), SIZELEFT(rp));
@ -8841,6 +8899,7 @@ mdb_put(MDB_txn *txn, MDB_dbi dbi,
{ {
MDB_cursor mc; MDB_cursor mc;
MDB_xcursor mx; MDB_xcursor mx;
int rc;
if (unlikely(!key || !data || !txn)) if (unlikely(!key || !data || !txn))
return EINVAL; return EINVAL;
@ -8858,7 +8917,11 @@ mdb_put(MDB_txn *txn, MDB_dbi dbi,
return (txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN; return (txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
mdb_cursor_init(&mc, txn, dbi, &mx); mdb_cursor_init(&mc, txn, dbi, &mx);
return mdb_cursor_put(&mc, key, data, flags); mc.mc_next = txn->mt_cursors[dbi];
txn->mt_cursors[dbi] = &mc;
rc = mdb_cursor_put(&mc, key, data, flags);
txn->mt_cursors[dbi] = mc.mc_next;
return rc;
} }
#ifndef MDB_WBUF #ifndef MDB_WBUF
@ -9850,6 +9913,7 @@ done:
} else if (rc == MDB_NOTFOUND) { } else if (rc == MDB_NOTFOUND) {
rc = MDB_SUCCESS; rc = MDB_SUCCESS;
} }
mc->mc_flags &= ~C_INITIALIZED;
return rc; return rc;
} }