mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-21 07:09:34 -05:00
ITS#7515 Fix mt_dirty_room in nested txns.
Fix description & code: Also ignore dirty pages hidden by spilled pages, as they won't merge into our dirty_list. Update it in mdb_page_flush() instead of mdb_page_spill().
This commit is contained in:
parent
cfe262dce9
commit
bc48a40621
1 changed files with 13 additions and 44 deletions
|
|
@ -892,7 +892,11 @@ struct MDB_txn {
|
||||||
#define MDB_TXN_SPILLS 0x08 /**< txn or a parent has spilled pages */
|
#define MDB_TXN_SPILLS 0x08 /**< txn or a parent has spilled pages */
|
||||||
/** @} */
|
/** @} */
|
||||||
unsigned int mt_flags; /**< @ref mdb_txn */
|
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;
|
unsigned int mt_dirty_room;
|
||||||
/** Tracks which of the two meta pages was used at the start
|
/** Tracks which of the two meta pages was used at the start
|
||||||
* of this transaction.
|
* of this transaction.
|
||||||
|
|
@ -1560,31 +1564,7 @@ mdb_page_spill(MDB_cursor *m0, MDB_val *key, MDB_val *data)
|
||||||
rc = mdb_pages_xkeep(m0, P_DIRTY|P_KEEP, i);
|
rc = mdb_pages_xkeep(m0, P_DIRTY|P_KEEP, i);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (rc == 0) {
|
txn->mt_flags |= rc ? MDB_TXN_ERROR : MDB_TXN_SPILLS;
|
||||||
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;
|
|
||||||
}
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1829,6 +1809,8 @@ mdb_page_unspill(MDB_txn *tx0, MDB_page *mp, MDB_page **ret)
|
||||||
if (x <= txn->mt_spill_pgs[0] && txn->mt_spill_pgs[x] == pn) {
|
if (x <= txn->mt_spill_pgs[0] && txn->mt_spill_pgs[x] == pn) {
|
||||||
MDB_page *np;
|
MDB_page *np;
|
||||||
int num;
|
int num;
|
||||||
|
if (txn->mt_dirty_room == 0)
|
||||||
|
return MDB_TXN_FULL;
|
||||||
if (IS_OVERFLOW(mp))
|
if (IS_OVERFLOW(mp))
|
||||||
num = mp->mp_pages;
|
num = mp->mp_pages;
|
||||||
else
|
else
|
||||||
|
|
@ -1857,21 +1839,6 @@ mdb_page_unspill(MDB_txn *tx0, MDB_page *mp, MDB_page **ret)
|
||||||
* page remains spilled until child commits
|
* 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);
|
mdb_page_dirty(tx0, np);
|
||||||
np->mp_flags |= P_DIRTY;
|
np->mp_flags |= P_DIRTY;
|
||||||
*ret = np;
|
*ret = np;
|
||||||
|
|
@ -2674,8 +2641,7 @@ mdb_page_flush(MDB_txn *txn, int keep)
|
||||||
}
|
}
|
||||||
dp->mp_flags &= ~P_DIRTY;
|
dp->mp_flags &= ~P_DIRTY;
|
||||||
}
|
}
|
||||||
dl[0].mid = j;
|
goto done;
|
||||||
return MDB_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the pages */
|
/* Write the pages */
|
||||||
|
|
@ -2769,8 +2735,11 @@ mdb_page_flush(MDB_txn *txn, int keep)
|
||||||
}
|
}
|
||||||
mdb_dpage_free(env, dp);
|
mdb_dpage_free(env, dp);
|
||||||
}
|
}
|
||||||
dl[0].mid = j;
|
|
||||||
|
|
||||||
|
done:
|
||||||
|
i--;
|
||||||
|
txn->mt_dirty_room += i - j;
|
||||||
|
dl[0].mid = j;
|
||||||
return MDB_SUCCESS;
|
return MDB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue