+/** Make shadow copies of all of parent txn's cursors */
+static int
+mdb_cursor_shadow(MDB_txn *src, MDB_txn *dst)
+{
+ MDB_cursor *mc, *m2;
+ unsigned int i, j, size;
+
+ for (i=0;i<src->mt_numdbs; i++) {
+ if (src->mt_cursors[i]) {
+ size = sizeof(MDB_cursor);
+ if (src->mt_cursors[i]->mc_xcursor)
+ size += sizeof(MDB_xcursor);
+ for (m2 = src->mt_cursors[i]; m2; m2=m2->mc_next) {
+ mc = malloc(size);
+ if (!mc)
+ return ENOMEM;
+ mc->mc_orig = m2;
+ mc->mc_txn = dst;
+ mc->mc_dbi = i;
+ mc->mc_db = &dst->mt_dbs[i];
+ mc->mc_dbx = m2->mc_dbx;
+ mc->mc_dbflag = &dst->mt_dbflags[i];
+ mc->mc_snum = m2->mc_snum;
+ mc->mc_top = m2->mc_top;
+ mc->mc_flags = m2->mc_flags | C_SHADOW;
+ for (j=0; j<mc->mc_snum; j++) {
+ mc->mc_pg[j] = m2->mc_pg[j];
+ mc->mc_ki[j] = m2->mc_ki[j];
+ }
+ 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 | C_SHADOW;
+ 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];
+ dst->mt_cursors[i] = mc;
+ }
+ }
+ }
+ return MDB_SUCCESS;
+}
+
+/** Merge shadow cursors back into parent's */
+static void
+mdb_cursor_merge(MDB_txn *txn)
+{
+ MDB_dbi i;
+ for (i=0; i<txn->mt_numdbs; i++) {
+ if (txn->mt_cursors[i]) {
+ MDB_cursor *mc;
+ while ((mc = txn->mt_cursors[i])) {
+ txn->mt_cursors[i] = mc->mc_next;
+ if (mc->mc_flags & C_SHADOW) {
+ MDB_cursor *m2 = mc->mc_orig;
+ unsigned int j;
+ m2->mc_snum = mc->mc_snum;
+ m2->mc_top = mc->mc_top;
+ for (j=0; j<mc->mc_snum; j++) {
+ m2->mc_pg[j] = mc->mc_pg[j];
+ m2->mc_ki[j] = mc->mc_ki[j];
+ }
+ }
+ if (mc->mc_flags & C_ALLOCD)
+ free(mc);
+ }
+ }
+ }
+}
+