#define MDB_TXN_SPILLS 0x08 /**< txn or a parent has spilled pages */
/** @} */
unsigned int mt_flags; /**< @ref mdb_txn */
- /** dirty_list maxsize - # of allocated pages allowed, including in parent txns */
+ /** dirty_list room: Array size - #dirty pages visible to this txn.
+ * Includes ancestor txns' dirty pages not hidden by other txns'
+ * dirty/spilled pages. Thus commit(nested txn) has room to merge
+ * dirty_list into mt_parent after freeing hidden mt_parent pages.
+ */
unsigned int mt_dirty_room;
/** Tracks which of the two meta pages was used at the start
* of this transaction.
rc = mdb_pages_xkeep(m0, P_DIRTY|P_KEEP, i);
done:
- if (rc == 0) {
- if (txn->mt_parent) {
- txn->mt_dirty_room = txn->mt_parent->mt_dirty_room - dl[0].mid;
- /* dirty pages that are dirty in an ancestor don't
- * count against this txn's dirty_room.
- */
- for (i=1; i<=dl[0].mid; i++) {
- pgno_t pgno = dl[i].mid;
- MDB_txn *tx2;
- for (tx2 = txn->mt_parent; tx2; tx2 = tx2->mt_parent) {
- j = mdb_mid2l_search(tx2->mt_u.dirty_list, pgno);
- if (j <= tx2->mt_u.dirty_list[0].mid &&
- tx2->mt_u.dirty_list[j].mid == pgno) {
- txn->mt_dirty_room++;
- break;
- }
- }
- }
- } else {
- txn->mt_dirty_room = MDB_IDL_UM_MAX - dl[0].mid;
- }
- txn->mt_flags |= MDB_TXN_SPILLS;
- } else {
- txn->mt_flags |= MDB_TXN_ERROR;
- }
+ txn->mt_flags |= rc ? MDB_TXN_ERROR : MDB_TXN_SPILLS;
return rc;
}
if (x <= txn->mt_spill_pgs[0] && txn->mt_spill_pgs[x] == pn) {
MDB_page *np;
int num;
+ if (txn->mt_dirty_room == 0)
+ return MDB_TXN_FULL;
if (IS_OVERFLOW(mp))
num = mp->mp_pages;
else
* page remains spilled until child commits
*/
- if (txn->mt_parent) {
- MDB_txn *tx2;
- /* If this page is also in a parent's dirty list, then
- * it's already accounted in dirty_room, and we need to
- * cancel out the decrement that mdb_page_dirty does.
- */
- for (tx2 = txn->mt_parent; tx2; tx2 = tx2->mt_parent) {
- x = mdb_mid2l_search(tx2->mt_u.dirty_list, pgno);
- if (x <= tx2->mt_u.dirty_list[0].mid &&
- tx2->mt_u.dirty_list[x].mid == pgno) {
- tx0->mt_dirty_room++;
- break;
- }
- }
- }
mdb_page_dirty(tx0, np);
np->mp_flags |= P_DIRTY;
*ret = np;
}
dp->mp_flags &= ~P_DIRTY;
}
- dl[0].mid = j;
- return MDB_SUCCESS;
+ goto done;
}
/* Write the pages */
}
mdb_dpage_free(env, dp);
}
- dl[0].mid = j;
+done:
+ i--;
+ txn->mt_dirty_room += i - j;
+ dl[0].mid = j;
return MDB_SUCCESS;
}