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.
vmware
Hallvard Furuseth 12 years ago
parent 9be6af0dcb
commit be47ca7667
  1. 112
      libraries/liblmdb/mdb.c

@ -879,8 +879,8 @@ struct MDB_xcursor;
struct MDB_cursor { struct MDB_cursor {
/** Next cursor on this DB in this txn */ /** Next cursor on this DB in this txn */
MDB_cursor *mc_next; MDB_cursor *mc_next;
/** Original cursor if this is a shadow */ /** Backup of the original cursor if this cursor is a shadow */
MDB_cursor *mc_orig; MDB_cursor *mc_backup;
/** Context used for databases with #MDB_DUPSORT, otherwise NULL */ /** Context used for databases with #MDB_DUPSORT, otherwise NULL */
struct MDB_xcursor *mc_xcursor; struct MDB_xcursor *mc_xcursor;
/** The transaction that owns this cursor */ /** The transaction that owns this cursor */
@ -1633,57 +1633,35 @@ mdb_env_sync(MDB_env *env, int force)
return rc; return rc;
} }
/** Make shadow copies of all of parent txn's cursors */ /** Back up parent txn's cursors, then grab the originals for tracking */
static int static int
mdb_cursor_shadow(MDB_txn *src, MDB_txn *dst) mdb_cursor_shadow(MDB_txn *src, MDB_txn *dst)
{ {
MDB_cursor *mc, *m2; MDB_cursor *mc, *bk;
unsigned int i, j, size; MDB_xcursor *mx;
size_t size;
int i;
for (i=0;i<src->mt_numdbs; i++) { for (i = src->mt_numdbs; --i >= 0; ) {
if (src->mt_cursors[i]) { if ((mc = src->mt_cursors[i]) != NULL) {
size = sizeof(MDB_cursor); size = sizeof(MDB_cursor);
if (src->mt_cursors[i]->mc_xcursor) if (mc->mc_xcursor)
size += sizeof(MDB_xcursor); size += sizeof(MDB_xcursor);
for (m2 = src->mt_cursors[i]; m2; m2=m2->mc_next) { for (; mc; mc = bk->mc_next) {
mc = malloc(size); bk = malloc(size);
if (!mc) if (!bk)
return ENOMEM; return ENOMEM;
mc->mc_orig = m2; *bk = *mc;
mc->mc_txn = dst; mc->mc_backup = bk;
mc->mc_dbi = i;
mc->mc_db = &dst->mt_dbs[i]; mc->mc_db = &dst->mt_dbs[i];
mc->mc_dbx = m2->mc_dbx; /* Kill pointers into src - and dst to reduce abuse: The
mc->mc_dbflag = &dst->mt_dbflags[i]; * user may not use mc until dst ends. Otherwise we'd...
mc->mc_snum = m2->mc_snum; */
mc->mc_top = m2->mc_top; mc->mc_txn = NULL; /* ...set this to dst */
mc->mc_flags = m2->mc_flags; mc->mc_dbflag = NULL; /* ...and &dst->mt_dbflags[i] */
for (j=0; j<mc->mc_snum; j++) { if ((mx = mc->mc_xcursor) != NULL) {
mc->mc_pg[j] = m2->mc_pg[j]; *(MDB_xcursor *)(bk+1) = *mx;
mc->mc_ki[j] = m2->mc_ki[j]; mx->mx_cursor.mc_txn = NULL; /* ...and dst. */
}
if (m2->mc_xcursor) {
MDB_xcursor *mx, *mx2;
mx = (MDB_xcursor *)(mc+1);
mc->mc_xcursor = mx;
mx2 = m2->mc_xcursor;
mx->mx_db = mx2->mx_db;
mx->mx_dbx = mx2->mx_dbx;
mx->mx_dbflag = mx2->mx_dbflag;
mx->mx_cursor.mc_txn = dst;
mx->mx_cursor.mc_dbi = mx2->mx_cursor.mc_dbi;
mx->mx_cursor.mc_db = &mx->mx_db;
mx->mx_cursor.mc_dbx = &mx->mx_dbx;
mx->mx_cursor.mc_dbflag = &mx->mx_dbflag;
mx->mx_cursor.mc_snum = mx2->mx_cursor.mc_snum;
mx->mx_cursor.mc_top = mx2->mx_cursor.mc_top;
mx->mx_cursor.mc_flags = mx2->mx_cursor.mc_flags;
for (j=0; j<mx2->mx_cursor.mc_snum; j++) {
mx->mx_cursor.mc_pg[j] = mx2->mx_cursor.mc_pg[j];
mx->mx_cursor.mc_ki[j] = mx2->mx_cursor.mc_ki[j];
}
} else {
mc->mc_xcursor = NULL;
} }
mc->mc_next = dst->mt_cursors[i]; mc->mc_next = dst->mt_cursors[i];
dst->mt_cursors[i] = mc; dst->mt_cursors[i] = mc;
@ -1693,32 +1671,40 @@ mdb_cursor_shadow(MDB_txn *src, MDB_txn *dst)
return MDB_SUCCESS; return MDB_SUCCESS;
} }
/** Close this write txn's cursors, after optionally merging its shadow /** Close this write txn's cursors, give parent txn's cursors back to parent.
* cursors back into parent's.
* @param[in] txn the transaction handle. * @param[in] txn the transaction handle.
* @param[in] merge zero to not merge cursors, non-zero to merge. * @param[in] merge true to keep changes to parent cursors, false to revert.
* @return 0 on success, non-zero on failure. * @return 0 on success, non-zero on failure.
*/ */
static void static void
mdb_cursors_close(MDB_txn *txn, unsigned merge) mdb_cursors_close(MDB_txn *txn, unsigned merge)
{ {
MDB_cursor **cursors = txn->mt_cursors, *mc, *next; MDB_cursor **cursors = txn->mt_cursors, *mc, *next, *bk;
int i, j; MDB_xcursor *mx;
int i;
for (i = txn->mt_numdbs; --i >= 0; ) { for (i = txn->mt_numdbs; --i >= 0; ) {
for (mc = cursors[i]; mc; mc = next) { for (mc = cursors[i]; mc; mc = next) {
next = mc->mc_next; next = mc->mc_next;
if (merge && mc->mc_orig) { if ((bk = mc->mc_backup) != NULL) {
MDB_cursor *m2 = mc->mc_orig; if (merge) {
m2->mc_snum = mc->mc_snum; /* Commit changes to parent txn */
m2->mc_top = mc->mc_top; mc->mc_next = bk->mc_next;
for (j = mc->mc_snum; --j >= 0; ) { mc->mc_backup = bk->mc_backup;
m2->mc_pg[j] = mc->mc_pg[j]; mc->mc_txn = bk->mc_txn;
m2->mc_ki[j] = mc->mc_ki[j]; mc->mc_db = bk->mc_db;
} mc->mc_dbflag = bk->mc_dbflag;
if ((mx = mc->mc_xcursor) != NULL)
mx->mx_cursor.mc_txn = bk->mc_txn;
} else {
/* Abort nested txn */
*mc = *bk;
if ((mx = mc->mc_xcursor) != NULL)
*mx = *(MDB_xcursor *)(bk+1);
} }
/* Only malloced cursors are permanently tracked. */ mc = bk;
free(mc); }
free(mc);
} }
cursors[i] = NULL; cursors[i] = NULL;
} }
@ -5867,7 +5853,7 @@ mdb_xcursor_init1(MDB_cursor *mc, MDB_node *node)
static void static void
mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx) mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx)
{ {
mc->mc_orig = NULL; mc->mc_backup = NULL;
mc->mc_dbi = dbi; mc->mc_dbi = dbi;
mc->mc_txn = txn; mc->mc_txn = txn;
mc->mc_db = &txn->mt_dbs[dbi]; mc->mc_db = &txn->mt_dbs[dbi];
@ -5961,7 +5947,7 @@ mdb_cursor_count(MDB_cursor *mc, size_t *countp)
void void
mdb_cursor_close(MDB_cursor *mc) mdb_cursor_close(MDB_cursor *mc)
{ {
if (mc != NULL) { if (mc && !mc->mc_backup) {
/* remove from txn, if tracked */ /* remove from txn, if tracked */
if ((mc->mc_flags & C_UNTRACK) && mc->mc_txn->mt_cursors) { if ((mc->mc_flags & C_UNTRACK) && mc->mc_txn->mt_cursors) {
MDB_cursor **prev = &mc->mc_txn->mt_cursors[mc->mc_dbi]; MDB_cursor **prev = &mc->mc_txn->mt_cursors[mc->mc_dbi];

Loading…
Cancel
Save