#define CURSOR_TOP(c) (&(c)->mc_stack[(c)->mc_snum-1])
#define CURSOR_PARENT(c) (&(c)->mc_stack[(c)->mc_snum-2])
+#define CURSOR_STACK 32
struct MDB_xcursor;
struct MDB_cursor {
MDB_txn *mc_txn;
- MDB_ppage mc_stack[32]; /* stack of parent pages */
+ MDB_ppage mc_stack[CURSOR_STACK]; /* stack of parent pages */
unsigned int mc_snum; /* number of pushed pages */
MDB_dbi mc_dbi;
short mc_initialized; /* 1 if initialized */
static int mdb_env_read_header(MDB_env *env, MDB_meta *meta);
static int mdb_env_read_meta(MDB_env *env, int *which);
static int mdb_env_write_meta(MDB_txn *txn);
-static MDB_page *mdb_get_page(MDB_txn *txn, pgno_t pgno);
+static int mdb_get_page(MDB_txn *txn, pgno_t pgno, MDB_page **mp);
static MDB_node *mdb_search_node(MDB_txn *txn, MDB_dbi dbi, MDB_page *mp,
MDB_val *key, int *exactp, unsigned int *kip);
if ((dp = mdb_alloc_page(txn, pp->mp_parent, pp->mp_pi, 1)) == NULL)
return ENOMEM;
DPRINTF("touched page %lu -> %lu", mp->mp_pgno, dp->p.mp_pgno);
+ assert(mp->mp_pgno != dp->p.mp_pgno);
mdb_midl_insert(txn->mt_free_pgs, mp->mp_pgno);
pgno = dp->p.mp_pgno;
memcpy(&dp->p, mp, txn->mt_env->me_psize);
return MDB_PANIC;
}
- if (!(txn->mt_flags & MDB_TXN_RDONLY)) {
- txn->mt_u.dirty_list = env->me_dirty_list;
- txn->mt_u.dirty_list[0].mid = 0;
- txn->mt_free_pgs = env->me_free_pgs;
- txn->mt_free_pgs[0] = 0;
-
- pthread_mutex_lock(&env->me_txns->mti_wmutex);
- env->me_txns->mti_txnid++;
- }
-
- txn->mt_txnid = env->me_txns->mti_txnid;
-
if (txn->mt_flags & MDB_TXN_RDONLY) {
MDB_reader *r = pthread_getspecific(env->me_txkey);
if (!r) {
env->me_txns->mti_numreaders = i+1;
pthread_mutex_unlock(&env->me_txns->mti_mutex);
}
+ txn->mt_txnid = env->me_txns->mti_txnid;
r->mr_txnid = txn->mt_txnid;
txn->mt_u.reader = r;
} else {
+ pthread_mutex_lock(&env->me_txns->mti_wmutex);
+
+ txn->mt_txnid = env->me_txns->mti_txnid+1;
+ txn->mt_u.dirty_list = env->me_dirty_list;
+ txn->mt_u.dirty_list[0].mid = 0;
+ txn->mt_free_pgs = env->me_free_pgs;
+ txn->mt_free_pgs[0] = 0;
env->me_txn = txn;
}
txn->mt_next_pgno = env->me_meta->mm_last_pg+1;
}
- DPRINTF("begin transaction %lu on mdbenv %p, root page %lu",
- txn->mt_txnid, (void *) env, txn->mt_dbs[MAIN_DBI].md_root);
+ DPRINTF("begin txn %p %lu%c on mdbenv %p, root page %lu", txn,
+ txn->mt_txnid, (txn->mt_flags & MDB_TXN_RDONLY) ? 'r' : 'w',
+ (void *) env, txn->mt_dbs[MAIN_DBI].md_root);
return MDB_SUCCESS;
}
}
env->me_txn = NULL;
- env->me_txns->mti_txnid--;
for (i=2; i<env->me_numdbs; i++)
env->me_dbxs[i].md_dirty = 0;
pthread_mutex_unlock(&env->me_txns->mti_wmutex);
if (!txn->mt_u.dirty_list[0].mid)
goto done;
- DPRINTF("committing transaction %lu on mdbenv %p, root page %lu",
+ DPRINTF("committing txn %p %lu on mdbenv %p, root page %lu", txn,
txn->mt_txnid, (void *) env, txn->mt_dbs[MAIN_DBI].md_root);
/* should only be one record now */
dp->p.mp_flags &= ~P_DIRTY;
if (++n >= MDB_COMMIT_PAGES) {
done = 0;
+ i++;
break;
}
}
}
txn->mt_u.dirty_list[i].mid = 0;
}
+ txn->mt_u.dirty_list[0].mid = 0;
if ((n = mdb_env_sync(env, 0)) != 0 ||
(n = mdb_env_write_meta(txn)) != MDB_SUCCESS) {
return n;
}
+ env->me_txns->mti_txnid = txn->mt_txnid;
+
done:
env->me_txn = NULL;
/* update the DB tables */
DPRINTF("pushing page %lu on db %u cursor %p", mp->mp_pgno,
cursor->mc_dbi, (void *) cursor);
+ assert(cursor->mc_snum < CURSOR_STACK);
+
ppage = &cursor->mc_stack[cursor->mc_snum++];
ppage->mp_page = mp;
ppage->mp_ki = 0;
return ppage;
}
-static MDB_page *
-mdb_get_page(MDB_txn *txn, pgno_t pgno)
+static int
+mdb_get_page(MDB_txn *txn, pgno_t pgno, MDB_page **ret)
{
MDB_page *p = NULL;
- int found = 0;
if (!F_ISSET(txn->mt_flags, MDB_TXN_RDONLY) && txn->mt_u.dirty_list[0].mid) {
MDB_dpage *dp;
if (x <= txn->mt_u.dirty_list[0].mid && txn->mt_u.dirty_list[x].mid == pgno) {
dp = txn->mt_u.dirty_list[x].mptr;
p = &dp->p;
- found = 1;
}
}
- if (!found) {
- if (pgno > txn->mt_env->me_meta->mm_last_pg)
- return NULL;
- p = (MDB_page *)(txn->mt_env->me_map + txn->mt_env->me_psize * pgno);
+ if (!p) {
+ if (pgno <= txn->mt_env->me_meta->mm_last_pg)
+ p = (MDB_page *)(txn->mt_env->me_map + txn->mt_env->me_psize * pgno);
+ }
+ *ret = p;
+ if (!p) {
+ DPRINTF("page %lu not found", pgno);
+ assert(p != NULL);
}
- return p;
+ return (p != NULL) ? MDB_SUCCESS : MDB_PAGE_NOTFOUND;
}
static int
CURSOR_TOP(cursor)->mp_ki = i;
mpp->mp_parent = mp;
- if ((mp = mdb_get_page(txn, NODEPGNO(node))) == NULL)
- return MDB_PAGE_NOTFOUND;
+ if ((rc = mdb_get_page(txn, NODEPGNO(node), &mp)))
+ return rc;
mpp->mp_pi = i;
mpp->mp_page = mp;
return MDB_NOTFOUND;
}
- if ((mpp->mp_page = mdb_get_page(txn, root)) == NULL)
- return MDB_PAGE_NOTFOUND;
+ if (rc = mdb_get_page(txn, root, &mpp->mp_page))
+ return rc;
- DPRINTF("root page has flags 0x%X", mpp->mp_page->mp_flags);
+ DPRINTF("db %u root page %lu has flags 0x%X",
+ dbi, root, mpp->mp_page->mp_flags);
if (modify) {
/* For sub-databases, update main root first */
{
MDB_page *omp; /* overflow mpage */
pgno_t pgno;
+ int rc;
if (!F_ISSET(leaf->mn_flags, F_BIGDATA)) {
data->mv_size = leaf->mn_dsize;
*/
data->mv_size = leaf->mn_dsize;
memcpy(&pgno, NODEDATA(leaf), sizeof(pgno));
- if ((omp = mdb_get_page(txn, pgno)) == NULL) {
+ if (rc = mdb_get_page(txn, pgno, &omp)) {
DPRINTF("read overflow page %lu failed", pgno);
- return MDB_PAGE_NOTFOUND;
+ return rc;
}
data->mv_data = METADATA(omp);
assert(IS_BRANCH(parent->mp_page));
indx = NODEPTR(parent->mp_page, parent->mp_ki);
- if ((mp = mdb_get_page(cursor->mc_txn, NODEPGNO(indx))) == NULL)
- return MDB_PAGE_NOTFOUND;
+ if (rc = mdb_get_page(cursor->mc_txn, NODEPGNO(indx), &mp))
+ return rc;;
#if 0
mp->parent = parent->mp_page;
mp->parent_index = parent->mp_ki;
} else {
dbn = 2;
}
+ DPRINTF("Sub-db %u for db %u root page %lu", dbn, dbi, db->md_root);
mx->mx_dbs[dbn] = *db;
mx->mx_dbxs[dbn].md_name.mv_data = NODEKEY(node);
mx->mx_dbxs[dbn].md_name.mv_size = node->mn_ksize;
MDB_page *root;
MDB_pageparent npp;
indx_t si = 0, di = 0;
+ int rc;
assert(txn != NULL);
assert(mpp != NULL);
} else if (IS_BRANCH(mpp->mp_page) && NUMKEYS(mpp->mp_page) == 1) {
DPUTS("collapsing root page!");
txn->mt_dbs[dbi].md_root = NODEPGNO(NODEPTR(mpp->mp_page, 0));
- if ((root = mdb_get_page(txn, txn->mt_dbs[dbi].md_root)) == NULL)
- return MDB_PAGE_NOTFOUND;
+ if (rc = mdb_get_page(txn, txn->mt_dbs[dbi].md_root, &root))
+ return rc;
txn->mt_dbs[dbi].md_depth--;
txn->mt_dbs[dbi].md_branch_pages--;
} else
*/
DPUTS("reading right neighbor");
node = NODEPTR(mpp->mp_parent, mpp->mp_pi + 1);
- if ((npp.mp_page = mdb_get_page(txn, NODEPGNO(node))) == NULL)
- return MDB_PAGE_NOTFOUND;
+ if (rc = mdb_get_page(txn, NODEPGNO(node), &npp.mp_page))
+ return rc;
npp.mp_pi = mpp->mp_pi + 1;
si = 0;
di = NUMKEYS(mpp->mp_page);
*/
DPUTS("reading left neighbor");
node = NODEPTR(mpp->mp_parent, mpp->mp_pi - 1);
- if ((npp.mp_page = mdb_get_page(txn, NODEPGNO(node))) == NULL)
- return MDB_PAGE_NOTFOUND;
+ if (rc = mdb_get_page(txn, NODEPGNO(node), &npp.mp_page))
+ return rc;
npp.mp_pi = mpp->mp_pi - 1;
si = NUMKEYS(npp.mp_page) - 1;
di = 0;
top = parent;
} else {
ni = NODEPTR(parent->mp_page, parent->mp_ki);
- top->mp_page = mdb_get_page(&mx.mx_txn, NODEPGNO(ni));
+ rc = mdb_get_page(&mx.mx_txn, NODEPGNO(ni), &top->mp_page);
}
}
}