char mn_data[1];
} MDB_node;
-typedef struct MDB_dbx {
- char *md_name;
- MDB_cmp_func *md_cmp; /* user compare function */
- MDB_rel_func *md_rel; /* user relocate function */
-} MDB_dbx;
-
typedef struct MDB_db {
uint32_t md_pad;
uint16_t md_flags;
pgno_t md_root;
} MDB_db;
+typedef struct MDB_dbx {
+ char *md_name;
+ MDB_cmp_func *md_cmp; /* user compare function */
+ MDB_cmp_func *md_dcmp; /* user dupsort function */
+ MDB_rel_func *md_rel; /* user relocate function */
+ MDB_db *md_db;
+ MDB_page *md_page;
+ unsigned int md_ki; /* cursor index on parent page */
+} MDB_dbx;
+
struct MDB_txn {
pgno_t mt_next_pgno; /* next unallocated page */
ULONG mt_txnid;
MDB_reader *reader;
} mt_u;
MDB_dbx *mt_dbxs; /* array */
- MDB_db **mt_dbs; /* array of ptrs */
MDB_db mt_db0; /* just for write txns */
unsigned int mt_numdbs;
MDB_oldpages *me_pghead;
MDB_oldpages *me_pgtail;
MDB_dbx *me_dbxs; /* array */
- MDB_db **me_dbs; /* array of ptrs */
unsigned int me_numdbs;
};
static int
_mdb_cmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *key1, const MDB_val *key2)
{
- if (F_ISSET(txn->mt_dbs[dbi]->md_flags, MDB_REVERSEKEY))
+ if (F_ISSET(txn->mt_dbxs[dbi].md_db->md_flags, MDB_REVERSEKEY))
return memnrcmp(key1->mv_data, key1->mv_size, key2->mv_data, key2->mv_size);
else
return memncmp((char *)key1->mv_data, key1->mv_size, key2->mv_data, key2->mv_size);
txn->mt_numdbs = env->me_numdbs;
rc = (txn->mt_numdbs % DBX_CHUNK) + 1;
txn->mt_dbxs = malloc(rc * DBX_CHUNK * sizeof(MDB_dbx));
- txn->mt_dbs = malloc(rc * DBX_CHUNK * sizeof(MDB_db *));
memcpy(txn->mt_dbxs, env->me_dbxs, txn->mt_numdbs * sizeof(MDB_dbx));
- memcpy(txn->mt_dbs, env->me_dbs, txn->mt_numdbs * sizeof(MDB_db *));
if (!rdonly) {
- memcpy(&txn->mt_db0, txn->mt_dbs[0], sizeof(txn->mt_db0));
- txn->mt_dbs[0] = &txn->mt_db0;
+ memcpy(&txn->mt_db0, txn->mt_dbxs[0].md_db, sizeof(txn->mt_db0));
+ txn->mt_dbxs[0].md_db = &txn->mt_db0;
if (toggle)
txn->mt_flags |= MDB_TXN_METOGGLE;
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[0]->md_root);
+ txn->mt_txnid, (void *) env, txn->mt_dbxs[0].md_db->md_root);
*ret = txn;
return MDB_SUCCESS;
env = txn->mt_env;
DPRINTF("abort transaction %lu on mdbenv %p, root page %lu",
- txn->mt_txnid, (void *) env, txn->mt_dbs[0]->md_root);
+ txn->mt_txnid, (void *) env, txn->mt_dbxs[0].md_db->md_root);
- free(txn->mt_dbs);
free(txn->mt_dbxs);
if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)) {
goto done;
DPRINTF("committing transaction %lu on mdbenv %p, root page %lu",
- txn->mt_txnid, (void *) env, txn->mt_dbs[0]->md_root);
+ txn->mt_txnid, (void *) env, txn->mt_dbxs[0].md_db->md_root);
/* Commit up to MDB_COMMIT_PAGES dirty pages to disk until done.
*/
{
MDB_dbx *p1 = env->me_dbxs;
- MDB_db **p2 = env->me_dbs;
- txn->mt_dbs[0] = env->me_dbs[0];
+ txn->mt_dbxs[0].md_db = env->me_dbxs[0].md_db;
env->me_dbxs = txn->mt_dbxs;
- env->me_dbs = txn->mt_dbs;
env->me_numdbs = txn->mt_numdbs;
- free(p2);
free(p1);
}
assert(txn != NULL);
assert(txn->mt_env != NULL);
- DPRINTF("writing meta page for root page %lu", txn->mt_dbs[0]->md_root);
+ DPRINTF("writing meta page for root page %lu", txn->mt_dbxs[0].md_db->md_root);
env = txn->mt_env;
meta.mm_txnid = txn->mt_txnid;
meta.mm_psize = env->me_meta.mm_psize;
meta.mm_flags = env->me_meta.mm_flags;
- meta.mm_depth = txn->mt_dbs[0]->md_depth;
- meta.mm_branch_pages = txn->mt_dbs[0]->md_branch_pages;
- meta.mm_leaf_pages = txn->mt_dbs[0]->md_leaf_pages;
- meta.mm_overflow_pages = txn->mt_dbs[0]->md_overflow_pages;
- meta.mm_entries = txn->mt_dbs[0]->md_entries;
- meta.mm_root = txn->mt_dbs[0]->md_root;
+ meta.mm_depth = txn->mt_dbxs[0].md_db->md_depth;
+ meta.mm_branch_pages = txn->mt_dbxs[0].md_db->md_branch_pages;
+ meta.mm_leaf_pages = txn->mt_dbxs[0].md_db->md_leaf_pages;
+ meta.mm_overflow_pages = txn->mt_dbxs[0].md_db->md_overflow_pages;
+ meta.mm_entries = txn->mt_dbxs[0].md_db->md_entries;
+ meta.mm_root = txn->mt_dbxs[0].md_db->md_root;
if (!F_ISSET(txn->mt_flags, MDB_TXN_METOGGLE))
off += env->me_meta.mm_psize;
if (excl)
mdbenv_share_locks(env);
env->me_dbxs = calloc(DBX_CHUNK, sizeof(MDB_dbx));
- env->me_dbs = calloc(DBX_CHUNK, sizeof(MDB_db *));
env->me_numdbs = 1;
- env->me_dbs[0] = (MDB_db *)&env->me_meta.mm_psize;
+ env->me_dbxs[0].md_db = (MDB_db *)&env->me_meta.mm_psize;
}
if (env == NULL)
return;
- free(env->me_dbs);
free(env->me_dbxs);
free(env->me_path);
DPRINTF("transaction has failed, must abort");
return EINVAL;
} else
- root = txn->mt_dbs[dbi]->md_root;
+ root = txn->mt_dbxs[dbi].md_db->md_root;
if (root == P_INVALID) { /* Tree is empty. */
DPRINTF("tree is empty");
mpp->mp_pi = 0;
if ((rc = mdb_touch(txn, mpp)))
return rc;
- txn->mt_dbs[dbi]->md_root = mpp->mp_page->mp_pgno;
+ txn->mt_dbxs[dbi].md_db->md_root = mpp->mp_page->mp_pgno;
}
return mdb_search_page_root(txn, dbi, key, cursor, modify, mpp);
dp->p.mp_upper = txn->mt_env->me_meta.mm_psize;
if (IS_BRANCH(&dp->p))
- txn->mt_dbs[dbi]->md_branch_pages++;
+ txn->mt_dbxs[dbi].md_db->md_branch_pages++;
else if (IS_LEAF(&dp->p))
- txn->mt_dbs[dbi]->md_leaf_pages++;
+ txn->mt_dbxs[dbi].md_db->md_leaf_pages++;
else if (IS_OVERFLOW(&dp->p)) {
- txn->mt_dbs[dbi]->md_overflow_pages += num;
+ txn->mt_dbxs[dbi].md_db->md_overflow_pages += num;
dp->p.mp_pages = num;
}
}
if (IS_LEAF(src->mp_page))
- txn->mt_dbs[dbi]->md_leaf_pages--;
+ txn->mt_dbxs[dbi].md_db->md_leaf_pages--;
else
- txn->mt_dbs[dbi]->md_branch_pages--;
+ txn->mt_dbxs[dbi].md_db->md_branch_pages--;
mpp.mp_page = src->mp_parent;
dh = (MDB_dhead *)src->mp_parent;
if (mpp->mp_parent == NULL) {
if (NUMKEYS(mpp->mp_page) == 0) {
DPRINTF("tree is completely empty");
- txn->mt_dbs[dbi]->md_root = P_INVALID;
- txn->mt_dbs[dbi]->md_depth--;
- txn->mt_dbs[dbi]->md_leaf_pages--;
+ txn->mt_dbxs[dbi].md_db->md_root = P_INVALID;
+ txn->mt_dbxs[dbi].md_db->md_depth--;
+ txn->mt_dbxs[dbi].md_db->md_leaf_pages--;
} else if (IS_BRANCH(mpp->mp_page) && NUMKEYS(mpp->mp_page) == 1) {
DPRINTF("collapsing root page!");
- txn->mt_dbs[dbi]->md_root = NODEPGNO(NODEPTR(mpp->mp_page, 0));
- if ((root = mdbenv_get_page(txn->mt_env, txn->mt_dbs[dbi]->md_root)) == NULL)
+ txn->mt_dbxs[dbi].md_db->md_root = NODEPGNO(NODEPTR(mpp->mp_page, 0));
+ if ((root = mdbenv_get_page(txn->mt_env, txn->mt_dbxs[dbi].md_db->md_root)) == NULL)
return MDB_FAIL;
- txn->mt_dbs[dbi]->md_depth--;
- txn->mt_dbs[dbi]->md_branch_pages--;
+ txn->mt_dbxs[dbi].md_db->md_depth--;
+ txn->mt_dbxs[dbi].md_db->md_branch_pages--;
} else
DPRINTF("root page doesn't need rebalancing");
return MDB_SUCCESS;
pg++;
}
}
- txn->mt_dbs[dbi]->md_entries--;
+ txn->mt_dbxs[dbi].md_db->md_entries--;
rc = mdb_rebalance(txn, dbi, &mpp);
if (rc != MDB_SUCCESS)
txn->mt_flags |= MDB_TXN_ERROR;
return MDB_FAIL;
mdp->h.md_pi = 0;
mdp->h.md_parent = &pdp->p;
- txn->mt_dbs[dbi]->md_root = pdp->p.mp_pgno;
+ txn->mt_dbxs[dbi].md_db->md_root = pdp->p.mp_pgno;
DPRINTF("root split! new root = %lu", pdp->p.mp_pgno);
- txn->mt_dbs[dbi]->md_depth++;
+ txn->mt_dbxs[dbi].md_db->md_depth++;
/* Add left (implicit) pointer. */
if (mdb_add_node(txn, dbi, &pdp->p, 0, NULL, NULL,
return ENOMEM;
}
mpp.mp_page = &dp->p;
- txn->mt_dbs[dbi]->md_root = mpp.mp_page->mp_pgno;
- txn->mt_dbs[dbi]->md_depth++;
+ txn->mt_dbxs[dbi].md_db->md_root = mpp.mp_page->mp_pgno;
+ txn->mt_dbxs[dbi].md_db->md_depth++;
ki = 0;
}
else
if (rc != MDB_SUCCESS)
txn->mt_flags |= MDB_TXN_ERROR;
else
- txn->mt_dbs[dbi]->md_entries++;
+ txn->mt_dbxs[dbi].md_db->md_entries++;
done:
return rc;
data.mv_data = &dummy;
memset(&dummy, 0, sizeof(dummy));
dummy.md_root = P_INVALID;
+ dummy.md_flags = flags & 0xffff;
rc = mdb_put(txn, 0, &key, &data, 0);
if (rc == MDB_SUCCESS)
rc = mdb_get(txn, 0, &key, &data);
/* Is there a free slot? */
if ((txn->mt_numdbs & (DBX_CHUNK-1)) == 0) {
MDB_dbx *p1;
- MDB_db **p2;
int i;
i = txn->mt_numdbs + DBX_CHUNK;
p1 = realloc(txn->mt_dbxs, i * sizeof(MDB_dbx));
if (p1 == NULL)
return ENOMEM;
txn->mt_dbxs = p1;
- p2 = realloc(txn->mt_dbs, i * sizeof(MDB_db *));
- if (p2 == NULL)
- return ENOMEM;
- txn->mt_dbs = p2;
}
txn->mt_dbxs[txn->mt_numdbs].md_name = strdup(name);
txn->mt_dbxs[txn->mt_numdbs].md_cmp = NULL;
+ txn->mt_dbxs[txn->mt_numdbs].md_dcmp = NULL;
txn->mt_dbxs[txn->mt_numdbs].md_rel = NULL;
- txn->mt_dbs[txn->mt_numdbs] = data.mv_data;
+ txn->mt_dbxs[txn->mt_numdbs].md_db = data.mv_data;
*dbi = txn->mt_numdbs;
txn->mt_numdbs++;
}
return EINVAL;
arg->ms_psize = txn->mt_env->me_meta.mm_psize;
- arg->ms_depth = txn->mt_dbs[dbi]->md_depth;
- arg->ms_branch_pages = txn->mt_dbs[dbi]->md_branch_pages;
- arg->ms_leaf_pages = txn->mt_dbs[dbi]->md_leaf_pages;
- arg->ms_overflow_pages = txn->mt_dbs[dbi]->md_overflow_pages;
- arg->ms_entries = txn->mt_dbs[dbi]->md_entries;
+ arg->ms_depth = txn->mt_dbxs[dbi].md_db->md_depth;
+ arg->ms_branch_pages = txn->mt_dbxs[dbi].md_db->md_branch_pages;
+ arg->ms_leaf_pages = txn->mt_dbxs[dbi].md_db->md_leaf_pages;
+ arg->ms_overflow_pages = txn->mt_dbxs[dbi].md_db->md_overflow_pages;
+ arg->ms_entries = txn->mt_dbxs[dbi].md_db->md_entries;
return MDB_SUCCESS;
}