Skip to content

Commit be47ca7

Browse files
committed
ITS#7515 Fix tracking of parent txn's cursors.
Restore mc_flags and xcursors, they were tracked but not merged. Simplify: Track parent txn's original cursors after backing them up, instead of tracking copies and merging them back at commit.
1 parent 9be6af0 commit be47ca7

File tree

1 file changed

+49
-63
lines changed

1 file changed

+49
-63
lines changed

libraries/liblmdb/mdb.c

Lines changed: 49 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -879,8 +879,8 @@ struct MDB_xcursor;
879879
struct MDB_cursor {
880880
/** Next cursor on this DB in this txn */
881881
MDB_cursor*mc_next;
882-
/** Original cursor if this is a shadow */
883-
MDB_cursor*mc_orig;
882+
/** Backup of the original cursor if this cursor is a shadow */
883+
MDB_cursor*mc_backup;
884884
/** Context used for databases with #MDB_DUPSORT, otherwise NULL */
885885
struct MDB_xcursor*mc_xcursor;
886886
/** The transaction that owns this cursor */
@@ -1633,57 +1633,35 @@ mdb_env_sync(MDB_env *env, int force)
16331633
return rc;
16341634
}
16351635

1636-
/** Make shadow copies of all of parent txn's cursors */
1636+
/** Back up parent txn's cursors, then grab the originals for tracking */
16371637
static int
16381638
mdb_cursor_shadow(MDB_txn *src, MDB_txn *dst)
16391639
{
1640-
MDB_cursor *mc, *m2;
1641-
unsigned int i, j, size;
1640+
MDB_cursor *mc, *bk;
1641+
MDB_xcursor *mx;
1642+
size_t size;
1643+
int i;
16421644

1643-
for (i=0;i<src->mt_numdbs; i++) {
1644-
if (src->mt_cursors[i]) {
1645+
for (i = src->mt_numdbs; --i >= 0; ) {
1646+
if ((mc = src->mt_cursors[i]) != NULL) {
16451647
size = sizeof(MDB_cursor);
1646-
if (src->mt_cursors[i]->mc_xcursor)
1648+
if (mc->mc_xcursor)
16471649
size += sizeof(MDB_xcursor);
1648-
for (m2 = src->mt_cursors[i]; m2; m2=m2->mc_next) {
1649-
mc = malloc(size);
1650-
if (!mc)
1650+
for (; mc; mc = bk->mc_next) {
1651+
bk = malloc(size);
1652+
if (!bk)
16511653
return ENOMEM;
1652-
mc->mc_orig = m2;
1653-
mc->mc_txn = dst;
1654-
mc->mc_dbi = i;
1654+
*bk = *mc;
1655+
mc->mc_backup = bk;
16551656
mc->mc_db = &dst->mt_dbs[i];
1656-
mc->mc_dbx = m2->mc_dbx;
1657-
mc->mc_dbflag = &dst->mt_dbflags[i];
1658-
mc->mc_snum = m2->mc_snum;
1659-
mc->mc_top = m2->mc_top;
1660-
mc->mc_flags = m2->mc_flags;
1661-
for (j=0; j<mc->mc_snum; j++) {
1662-
mc->mc_pg[j] = m2->mc_pg[j];
1663-
mc->mc_ki[j] = m2->mc_ki[j];
1664-
}
1665-
if (m2->mc_xcursor) {
1666-
MDB_xcursor *mx, *mx2;
1667-
mx = (MDB_xcursor *)(mc+1);
1668-
mc->mc_xcursor = mx;
1669-
mx2 = m2->mc_xcursor;
1670-
mx->mx_db = mx2->mx_db;
1671-
mx->mx_dbx = mx2->mx_dbx;
1672-
mx->mx_dbflag = mx2->mx_dbflag;
1673-
mx->mx_cursor.mc_txn = dst;
1674-
mx->mx_cursor.mc_dbi = mx2->mx_cursor.mc_dbi;
1675-
mx->mx_cursor.mc_db = &mx->mx_db;
1676-
mx->mx_cursor.mc_dbx = &mx->mx_dbx;
1677-
mx->mx_cursor.mc_dbflag = &mx->mx_dbflag;
1678-
mx->mx_cursor.mc_snum = mx2->mx_cursor.mc_snum;
1679-
mx->mx_cursor.mc_top = mx2->mx_cursor.mc_top;
1680-
mx->mx_cursor.mc_flags = mx2->mx_cursor.mc_flags;
1681-
for (j=0; j<mx2->mx_cursor.mc_snum; j++) {
1682-
mx->mx_cursor.mc_pg[j] = mx2->mx_cursor.mc_pg[j];
1683-
mx->mx_cursor.mc_ki[j] = mx2->mx_cursor.mc_ki[j];
1684-
}
1685-
} else {
1686-
mc->mc_xcursor = NULL;
1657+
/* Kill pointers into src - and dst to reduce abuse: The
1658+
* user may not use mc until dst ends. Otherwise we'd...
1659+
*/
1660+
mc->mc_txn = NULL;/* ...set this to dst */
1661+
mc->mc_dbflag = NULL;/* ...and &dst->mt_dbflags[i] */
1662+
if ((mx = mc->mc_xcursor) != NULL) {
1663+
*(MDB_xcursor *)(bk+1) = *mx;
1664+
mx->mx_cursor.mc_txn = NULL; /* ...and dst. */
16871665
}
16881666
mc->mc_next = dst->mt_cursors[i];
16891667
dst->mt_cursors[i] = mc;
@@ -1693,32 +1671,40 @@ mdb_cursor_shadow(MDB_txn *src, MDB_txn *dst)
16931671
return MDB_SUCCESS;
16941672
}
16951673

1696-
/** Close this write txn's cursors, after optionally merging its shadow
1697-
* cursors back into parent's.
1674+
/** Close this write txn's cursors, give parent txn's cursors back to parent.
16981675
* @param[in] txn the transaction handle.
1699-
* @param[in] merge zero to not merge cursors, non-zero to merge.
1676+
* @param[in] merge true to keep changes to parent cursors, false to revert.
17001677
* @return 0 on success, non-zero on failure.
17011678
*/
17021679
static void
17031680
mdb_cursors_close(MDB_txn *txn, unsigned merge)
17041681
{
1705-
MDB_cursor **cursors = txn->mt_cursors, *mc, *next;
1706-
int i, j;
1682+
MDB_cursor **cursors = txn->mt_cursors, *mc, *next, *bk;
1683+
MDB_xcursor *mx;
1684+
int i;
17071685

17081686
for (i = txn->mt_numdbs; --i >= 0; ) {
17091687
for (mc = cursors[i]; mc; mc = next) {
1710-
next = mc->mc_next;
1711-
if (merge && mc->mc_orig) {
1712-
MDB_cursor *m2 = mc->mc_orig;
1713-
m2->mc_snum = mc->mc_snum;
1714-
m2->mc_top = mc->mc_top;
1715-
for (j = mc->mc_snum; --j >= 0; ) {
1716-
m2->mc_pg[j] = mc->mc_pg[j];
1717-
m2->mc_ki[j] = mc->mc_ki[j];
1718-
}
1688+
next = mc->mc_next;
1689+
if ((bk = mc->mc_backup) != NULL) {
1690+
if (merge) {
1691+
/* Commit changes to parent txn */
1692+
mc->mc_next = bk->mc_next;
1693+
mc->mc_backup = bk->mc_backup;
1694+
mc->mc_txn = bk->mc_txn;
1695+
mc->mc_db = bk->mc_db;
1696+
mc->mc_dbflag = bk->mc_dbflag;
1697+
if ((mx = mc->mc_xcursor) != NULL)
1698+
mx->mx_cursor.mc_txn = bk->mc_txn;
1699+
} else {
1700+
/* Abort nested txn */
1701+
*mc = *bk;
1702+
if ((mx = mc->mc_xcursor) != NULL)
1703+
*mx = *(MDB_xcursor *)(bk+1);
17191704
}
1720-
/* Only malloced cursors are permanently tracked. */
1721-
free(mc);
1705+
mc = bk;
1706+
}
1707+
free(mc);
17221708
}
17231709
cursors[i] = NULL;
17241710
}
@@ -5867,7 +5853,7 @@ mdb_xcursor_init1(MDB_cursor *mc, MDB_node *node)
58675853
static void
58685854
mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx)
58695855
{
5870-
mc->mc_orig = NULL;
5856+
mc->mc_backup = NULL;
58715857
mc->mc_dbi = dbi;
58725858
mc->mc_txn = txn;
58735859
mc->mc_db = &txn->mt_dbs[dbi];
@@ -5961,7 +5947,7 @@ mdb_cursor_count(MDB_cursor *mc, size_t *countp)
59615947
void
59625948
mdb_cursor_close(MDB_cursor *mc)
59635949
{
5964-
if (mc != NULL) {
5950+
if (mc && !mc->mc_backup) {
59655951
/* remove from txn, if tracked */
59665952
if ((mc->mc_flags & C_UNTRACK) && mc->mc_txn->mt_cursors) {
59675953
MDB_cursor **prev = &mc->mc_txn->mt_cursors[mc->mc_dbi];

0 commit comments

Comments
 (0)