mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-21 15:19:34 -05:00
ITS#7455 use freelist for overflow pages
This commit is contained in:
parent
185136397d
commit
f165507199
1 changed files with 113 additions and 28 deletions
|
|
@ -1242,6 +1242,7 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp)
|
||||||
MDB_page *np;
|
MDB_page *np;
|
||||||
pgno_t pgno = P_INVALID;
|
pgno_t pgno = P_INVALID;
|
||||||
MDB_ID2 mid;
|
MDB_ID2 mid;
|
||||||
|
txnid_t oldest = 0, last;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
*mp = NULL;
|
*mp = NULL;
|
||||||
|
|
@ -1254,12 +1255,11 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp)
|
||||||
if (!txn->mt_env->me_pghead &&
|
if (!txn->mt_env->me_pghead &&
|
||||||
txn->mt_dbs[FREE_DBI].md_root != P_INVALID) {
|
txn->mt_dbs[FREE_DBI].md_root != P_INVALID) {
|
||||||
/* See if there's anything in the free DB */
|
/* See if there's anything in the free DB */
|
||||||
int j;
|
|
||||||
MDB_reader *r;
|
MDB_reader *r;
|
||||||
MDB_cursor m2;
|
MDB_cursor m2;
|
||||||
MDB_node *leaf;
|
MDB_node *leaf;
|
||||||
MDB_val data;
|
MDB_val data;
|
||||||
txnid_t *kptr, last;
|
txnid_t *kptr;
|
||||||
|
|
||||||
mdb_cursor_init(&m2, txn, FREE_DBI, NULL);
|
mdb_cursor_init(&m2, txn, FREE_DBI, NULL);
|
||||||
if (!txn->mt_env->me_pgfirst) {
|
if (!txn->mt_env->me_pgfirst) {
|
||||||
|
|
@ -1282,15 +1282,21 @@ again:
|
||||||
last = *(txnid_t *)key.mv_data;
|
last = *(txnid_t *)key.mv_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unusable if referred by a meta page or reader... */
|
{
|
||||||
j = 1;
|
unsigned int i, nr;
|
||||||
if (last < txn->mt_txnid-1) {
|
txnid_t mr;
|
||||||
j = txn->mt_env->me_txns->mti_numreaders;
|
oldest = txn->mt_txnid - 1;
|
||||||
r = txn->mt_env->me_txns->mti_readers + j;
|
nr = txn->mt_env->me_txns->mti_numreaders;
|
||||||
for (j = -j; j && (last<r[j].mr_txnid || !r[j].mr_pid); j++) ;
|
r = txn->mt_env->me_txns->mti_readers;
|
||||||
|
for (i=0; i<nr; i++) {
|
||||||
|
if (!r[i].mr_pid) continue;
|
||||||
|
mr = r[i].mr_txnid;
|
||||||
|
if (mr < oldest)
|
||||||
|
oldest = mr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!j) {
|
if (oldest > last) {
|
||||||
/* It's usable, grab it.
|
/* It's usable, grab it.
|
||||||
*/
|
*/
|
||||||
MDB_oldpages *mop;
|
MDB_oldpages *mop;
|
||||||
|
|
@ -1331,19 +1337,99 @@ none:
|
||||||
if (txn->mt_env->me_pghead) {
|
if (txn->mt_env->me_pghead) {
|
||||||
MDB_oldpages *mop = txn->mt_env->me_pghead;
|
MDB_oldpages *mop = txn->mt_env->me_pghead;
|
||||||
if (num > 1) {
|
if (num > 1) {
|
||||||
/* FIXME: For now, always use fresh pages. We
|
MDB_cursor m2;
|
||||||
* really ought to search the free list for a
|
int retry = 2, readit = 0, n2 = num-1;
|
||||||
* contiguous range.
|
unsigned int i, j, k;
|
||||||
*/
|
|
||||||
;
|
/* If current list is too short, must fetch more and coalesce */
|
||||||
|
if (mop->mo_pages[0] < (unsigned)num)
|
||||||
|
readit = 1;
|
||||||
|
|
||||||
|
mdb_cursor_init(&m2, txn, FREE_DBI, NULL);
|
||||||
|
do {
|
||||||
|
if (readit) {
|
||||||
|
MDB_val key, data;
|
||||||
|
MDB_oldpages *mop2;
|
||||||
|
pgno_t *idl;
|
||||||
|
int exact;
|
||||||
|
|
||||||
|
last = mop->mo_txnid + 1;
|
||||||
|
|
||||||
|
/* We haven't hit the readers list yet? */
|
||||||
|
if (!oldest) {
|
||||||
|
MDB_reader *r;
|
||||||
|
unsigned int nr;
|
||||||
|
txnid_t mr;
|
||||||
|
|
||||||
|
oldest = txn->mt_txnid - 1;
|
||||||
|
nr = txn->mt_env->me_txns->mti_numreaders;
|
||||||
|
r = txn->mt_env->me_txns->mti_readers;
|
||||||
|
for (i=0; i<nr; i++) {
|
||||||
|
if (!r[i].mr_pid) continue;
|
||||||
|
mr = r[i].mr_txnid;
|
||||||
|
if (mr < oldest)
|
||||||
|
oldest = mr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There's nothing we can use on the freelist */
|
||||||
|
if (oldest - last < 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
exact = 0;
|
||||||
|
key.mv_data = &last;
|
||||||
|
key.mv_size = sizeof(last);
|
||||||
|
rc = mdb_cursor_set(&m2, &key, &data, MDB_SET, &exact);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
idl = (MDB_ID *) data.mv_data;
|
||||||
|
mop2 = malloc(sizeof(MDB_oldpages) + MDB_IDL_SIZEOF(idl) - 2*sizeof(pgno_t) + MDB_IDL_SIZEOF(mop->mo_pages));
|
||||||
|
if (!mop2)
|
||||||
|
return ENOMEM;
|
||||||
|
/* merge in sorted order */
|
||||||
|
i = idl[0]; j = mop->mo_pages[0]; mop2->mo_pages[0] = k = i+j;
|
||||||
|
mop->mo_pages[0] = P_INVALID;
|
||||||
|
while (i>0 || j>0) {
|
||||||
|
if (i && idl[i] < mop->mo_pages[j])
|
||||||
|
mop2->mo_pages[k--] = idl[i--];
|
||||||
|
else
|
||||||
|
mop2->mo_pages[k--] = mop->mo_pages[j--];
|
||||||
|
}
|
||||||
|
txn->mt_env->me_pglast = last;
|
||||||
|
mop2->mo_txnid = last;
|
||||||
|
mop2->mo_next = mop->mo_next;
|
||||||
|
txn->mt_env->me_pghead = mop2;
|
||||||
|
free(mop);
|
||||||
|
mop = mop2;
|
||||||
|
/* Keep trying to read until we have enough */
|
||||||
|
if (mop->mo_pages[0] < (unsigned)num) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* current list has enough pages, but are they contiguous? */
|
||||||
|
for (i=mop->mo_pages[0]; i>=(unsigned)num; i--) {
|
||||||
|
if (mop->mo_pages[i-n2] == mop->mo_pages[i] + n2) {
|
||||||
|
pgno = mop->mo_pages[i];
|
||||||
|
i -= n2;
|
||||||
|
/* move any stragglers down */
|
||||||
|
for (j=i+num; j<=mop->mo_pages[0]; j++)
|
||||||
|
mop->mo_pages[i++] = mop->mo_pages[j];
|
||||||
|
mop->mo_pages[0] -= num;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop if we succeeded, or no more retries */
|
||||||
|
if (!retry || pgno != P_INVALID)
|
||||||
|
break;
|
||||||
|
readit = 1;
|
||||||
|
retry--;
|
||||||
|
|
||||||
|
} while (1);
|
||||||
} else {
|
} else {
|
||||||
/* peel pages off tail, so we only have to truncate the list */
|
/* peel pages off tail, so we only have to truncate the list */
|
||||||
pgno = MDB_IDL_LAST(mop->mo_pages);
|
pgno = MDB_IDL_LAST(mop->mo_pages);
|
||||||
if (MDB_IDL_IS_RANGE(mop->mo_pages)) {
|
|
||||||
mop->mo_pages[2]++;
|
|
||||||
if (mop->mo_pages[2] > mop->mo_pages[1])
|
|
||||||
mop->mo_pages[0] = 0;
|
|
||||||
} else {
|
|
||||||
mop->mo_pages[0]--;
|
mop->mo_pages[0]--;
|
||||||
}
|
}
|
||||||
if (MDB_IDL_IS_ZERO(mop->mo_pages)) {
|
if (MDB_IDL_IS_ZERO(mop->mo_pages)) {
|
||||||
|
|
@ -1357,7 +1443,6 @@ none:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (pgno == P_INVALID) {
|
if (pgno == P_INVALID) {
|
||||||
/* DB size is maxed out */
|
/* DB size is maxed out */
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue