#define mp_next mp_p.p_next
union {
pgno_t p_pgno; /**< page number */
- void * p_next; /**< for in-memory list of freed structs */
+ struct MDB_page *p_next; /**< for in-memory list of freed pages */
} mp_p;
uint16_t mp_pad;
/** @defgroup mdb_page Page Flags
#define OVPAGES(size, psize) ((PAGEHDRSZ-1 + (size)) / (psize) + 1)
/** Link in #MDB_txn.%mt_loose_pages list */
-#define NEXT_LOOSE_PAGE(p) (*(MDB_page **)METADATA(p))
+#define NEXT_LOOSE_PAGE(p) (*(MDB_page **)((p) + 2))
/** Header for a single key/data pair within a page.
* Used in pages of type #P_BRANCH and #P_LEAF without #P_LEAF2.
}
}
if (loose) {
+ DPRINTF(("loosen db %d page %"Z"u", DDBI(mc),
+ mp->mp_pgno));
NEXT_LOOSE_PAGE(mp) = mc->mc_txn->mt_loose_pgs;
mc->mc_txn->mt_loose_pgs = mp;
mp->mp_flags |= P_LOOSE;
static int
mdb_pages_xkeep(MDB_cursor *mc, unsigned pflags, int all)
{
- enum { Mask = P_SUBP|P_DIRTY|P_KEEP };
+ enum { Mask = P_SUBP|P_DIRTY|P_LOOSE|P_KEEP };
MDB_txn *txn = mc->mc_txn;
MDB_cursor *m3;
MDB_xcursor *mx;
break;
}
- /* Loose pages shouldn't be spilled */
- for (dp = txn->mt_loose_pgs; dp; dp = NEXT_LOOSE_PAGE(dp)) {
- if ((dp->mp_flags & Mask) == pflags)
- dp->mp_flags ^= P_KEEP;
- }
-
if (all) {
/* Mark dirty root pages */
for (i=0; i<txn->mt_numdbs; i++) {
for (i=dl[0].mid; i && need; i--) {
MDB_ID pn = dl[i].mid << 1;
dp = dl[i].mptr;
- if (dp->mp_flags & P_KEEP)
+ if (dp->mp_flags & (P_LOOSE|P_KEEP))
continue;
/* Can't spill twice, make sure it's not already in a parent's
* spill list.
if (num == 1 && txn->mt_loose_pgs) {
np = txn->mt_loose_pgs;
txn->mt_loose_pgs = NEXT_LOOSE_PAGE(np);
+ DPRINTF(("db %d use loose page %"Z"u", DDBI(mc),
+ np->mp_pgno));
*mp = np;
return MDB_SUCCESS;
}
while (++i <= pagecount) {
dp = dl[i].mptr;
/* Don't flush this page yet */
- if (dp->mp_flags & P_KEEP) {
- dp->mp_flags ^= P_KEEP;
+ if (dp->mp_flags & (P_LOOSE|P_KEEP)) {
+ dp->mp_flags &= ~P_KEEP;
dl[++j] = dl[i];
continue;
}
if (++i <= pagecount) {
dp = dl[i].mptr;
/* Don't flush this page yet */
- if (dp->mp_flags & P_KEEP) {
- dp->mp_flags ^= P_KEEP;
+ if (dp->mp_flags & (P_LOOSE|P_KEEP)) {
+ dp->mp_flags &= ~P_KEEP;
dl[i].mid = 0;
continue;
}
if (txn->mt_parent) {
MDB_txn *parent = txn->mt_parent;
+ MDB_page **lp;
MDB_ID2L dst, src;
MDB_IDL pspill;
unsigned x, y, len, ps_len;
}
}
+ /* Append our loose page list to parent's */
+ for (lp = &parent->mt_loose_pgs; *lp; lp = &NEXT_LOOSE_PAGE(lp))
+ ;
+ *lp = txn->mt_loose_pgs;
+
parent->mt_child = NULL;
mdb_midl_free(((MDB_ntxn *)txn)->mnt_pgstate.mf_pghead);
free(txn);