|
|
|
@ -1328,6 +1328,27 @@ none: |
|
|
|
|
return np; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** Copy a page: avoid copying unused portions of the page.
|
|
|
|
|
* @param[in] dst page to copy into |
|
|
|
|
* @param[in] src page to copy from |
|
|
|
|
*/ |
|
|
|
|
static void |
|
|
|
|
mdb_page_copy(MDB_page *dst, MDB_page *src, unsigned int psize) |
|
|
|
|
{ |
|
|
|
|
dst->mp_flags = src->mp_flags | P_DIRTY; |
|
|
|
|
dst->mp_pages = src->mp_pages; |
|
|
|
|
|
|
|
|
|
if (IS_LEAF2(src)) { |
|
|
|
|
memcpy(dst->mp_ptrs, src->mp_ptrs, psize - PAGEHDRSZ - SIZELEFT(src)); |
|
|
|
|
} else { |
|
|
|
|
unsigned int i, nkeys = NUMKEYS(src); |
|
|
|
|
for (i=0; i<nkeys; i++) |
|
|
|
|
dst->mp_ptrs[i] = src->mp_ptrs[i]; |
|
|
|
|
memcpy((char *)dst+src->mp_upper, (char *)src+src->mp_upper, |
|
|
|
|
psize - src->mp_upper); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** Touch a page: make it dirty and re-insert into tree with updated pgno.
|
|
|
|
|
* @param[in] mc cursor pointing to the page to be touched |
|
|
|
|
* @return 0 on success, non-zero on failure. |
|
|
|
@ -1345,11 +1366,16 @@ mdb_page_touch(MDB_cursor *mc) |
|
|
|
|
DPRINTF("touched db %u page %zu -> %zu", mc->mc_dbi, mp->mp_pgno, np->mp_pgno); |
|
|
|
|
assert(mp->mp_pgno != np->mp_pgno); |
|
|
|
|
mdb_midl_append(&mc->mc_txn->mt_free_pgs, mp->mp_pgno); |
|
|
|
|
pgno = np->mp_pgno; |
|
|
|
|
memcpy(np, mp, mc->mc_txn->mt_env->me_psize); |
|
|
|
|
if (SIZELEFT(mp)) { |
|
|
|
|
/* If page isn't full, just copy the used portion */ |
|
|
|
|
mdb_page_copy(np, mp, mc->mc_txn->mt_env->me_psize); |
|
|
|
|
} else { |
|
|
|
|
pgno = np->mp_pgno; |
|
|
|
|
memcpy(np, mp, mc->mc_txn->mt_env->me_psize); |
|
|
|
|
np->mp_pgno = pgno; |
|
|
|
|
np->mp_flags |= P_DIRTY; |
|
|
|
|
} |
|
|
|
|
mp = np; |
|
|
|
|
mp->mp_pgno = pgno; |
|
|
|
|
mp->mp_flags |= P_DIRTY; |
|
|
|
|
|
|
|
|
|
finish: |
|
|
|
|
/* Adjust other cursors pointing to mp */ |
|
|
|
|