/** @brief Set environment flags.
*
* This may be used to set some flags in addition to those from
- * #mdb_env_open(), or to unset these flags.
+ * #mdb_env_open(), or to unset these flags. If several threads
+ * change the flags at the same time, the result is undefined.
* @param[in] env An environment handle returned by #mdb_env_create()
* @param[in] flags The flags to change, bitwise OR'ed together
* @param[in] onoff A non-zero value sets the flags, zero clears them.
* Disabled if liblmdb is buillt with NDEBUG.
* @note This hack should become obsolete as lmdb's error handling matures.
* @param[in] env An environment handle returned by #mdb_env_create().
- * @parem[in] func An #MDB_assert_func function, or 0.
+ * @param[in] func An #MDB_assert_func function, or 0.
* @return A non-zero error value on failure and 0 on success.
*/
int mdb_env_set_assert(MDB_env *env, MDB_assert_func *func);
* <ul>
* <li>#MDB_CURRENT - overwrite the data of the key/data pair to which
* the cursor refers with the specified data item. The \b key
- * parameter is ignored.
+ * parameter is ignored. The \b data size must match the original.
* <li>#MDB_NODUPDATA - enter the new key/data pair only if it does not
* already appear in the database. This flag may only be specified
* if the database was opened with #MDB_DUPSORT. The function will
/** @brief The maximum size of a database page.
*
- * This is 32k, since it must fit in #MDB_page.#mp_upper.
+ * This is 32k, since it must fit in #MDB_page.%mp_upper.
*
* LMDB will use database pages < OS pages if needed.
* That causes more I/O in write transactions: The OS must
* @{
*/
#define MDB_TXN_RDONLY 0x01 /**< read-only transaction */
-#define MDB_TXN_ERROR 0x02 /**< an error has occurred */
+#define MDB_TXN_ERROR 0x02 /**< txn is unusable after an error */
#define MDB_TXN_DIRTY 0x04 /**< must write, even if dirty list is empty */
#define MDB_TXN_SPILLS 0x08 /**< txn or a parent has spilled pages */
/** @} */
unsigned int mt_flags; /**< @ref mdb_txn */
- /** dirty_list room: Array size - #dirty pages visible to this txn.
+ /** #dirty_list room: Array size - \#dirty pages visible to this txn.
* Includes ancestor txns' dirty pages not hidden by other txns'
* dirty/spilled pages. Thus commit(nested txn) has room to merge
* dirty_list into mt_parent after freeing hidden mt_parent pages.
#define MDB_ENV_ACTIVE 0x20000000U
/** me_txkey is set */
#define MDB_ENV_TXKEY 0x10000000U
- /** Have liveness lock in reader table */
-#define MDB_LIVE_READER 0x08000000U
uint32_t me_flags; /**< @ref mdb_env */
unsigned int me_psize; /**< DB page size, inited from me_os_psize */
unsigned int me_os_psize; /**< OS page size, from #GET_PAGESIZE */
#if !(MDB_MAXKEYSIZE)
unsigned int me_maxkey; /**< max size of a key */
#endif
+ int me_live_reader; /**< have liveness lock in reader table */
#ifdef _WIN32
int me_pidquery; /**< Used in OpenProcess */
HANDLE me_rmutex; /* Windows mutexes don't reside in shared mem */
#define MDB_COMMIT_PAGES IOV_MAX
#endif
- /* max bytes to write in one call */
+ /** max bytes to write in one call */
#define MAX_WRITE (0x80000000U >> (sizeof(ssize_t) == 4))
+ /** Check \b txn and \b dbi arguments to a function */
+#define TXN_DBI_EXIST(txn, dbi) \
+ ((txn) && (dbi) < (txn)->mt_numdbs && ((txn)->mt_dbflags[dbi] & DB_VALID))
+
static int mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp);
static int mdb_page_new(MDB_cursor *mc, uint32_t flags, int num, MDB_page **mp);
static int mdb_page_touch(MDB_cursor *mc);
static void mdb_cursor_pop(MDB_cursor *mc);
static int mdb_cursor_push(MDB_cursor *mc, MDB_page *mp);
-static int mdb_cursor_del0(MDB_cursor *mc, MDB_node *leaf);
+static int mdb_cursor_del0(MDB_cursor *mc);
+static int mdb_del0(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, unsigned flags);
static int mdb_cursor_sibling(MDB_cursor *mc, int move_right);
static int mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op);
static int mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op);
return buf;
}
+static const char *
+mdb_leafnode_type(MDB_node *n)
+{
+ static char *const tp[2][2] = {{"", ": DB"}, {": sub-page", ": sub-DB"}};
+ return F_ISSET(n->mn_flags, F_BIGDATA) ? ": overflow page" :
+ tp[F_ISSET(n->mn_flags, F_DUPDATA)][F_ISSET(n->mn_flags, F_SUBDATA)];
+}
+
/** Display all the keys in the page. */
void
mdb_page_list(MDB_page *mp)
{
+ pgno_t pgno = mdb_dbg_pgno(mp);
+ const char *type, *state = (mp->mp_flags & P_DIRTY) ? ", dirty" : "";
MDB_node *node;
unsigned int i, nkeys, nsize, total = 0;
MDB_val key;
DKBUF;
+ switch (mp->mp_flags & (P_BRANCH|P_LEAF|P_LEAF2|P_META|P_OVERFLOW|P_SUBP)) {
+ case P_BRANCH: type = "Branch page"; break;
+ case P_LEAF: type = "Leaf page"; break;
+ case P_LEAF|P_SUBP: type = "Sub-page"; break;
+ case P_LEAF|P_LEAF2: type = "LEAF2 page"; break;
+ case P_LEAF|P_LEAF2|P_SUBP: type = "LEAF2 sub-page"; break;
+ case P_OVERFLOW:
+ fprintf(stderr, "Overflow page %"Z"u pages %u%s\n",
+ pgno, mp->mp_pages, state);
+ return;
+ case P_META:
+ fprintf(stderr, "Meta-page %"Z"u txnid %"Z"u\n",
+ pgno, ((MDB_meta *)METADATA(mp))->mm_txnid);
+ return;
+ default:
+ fprintf(stderr, "Bad page %"Z"u flags 0x%u\n", pgno, mp->mp_flags);
+ return;
+ }
+
nkeys = NUMKEYS(mp);
- fprintf(stderr, "Page %"Z"u numkeys %d\n", mdb_dbg_pgno(mp), nkeys);
+ fprintf(stderr, "%s %"Z"u numkeys %d%s\n", type, pgno, nkeys, state);
+
for (i=0; i<nkeys; i++) {
+ if (IS_LEAF2(mp)) { /* LEAF2 pages have no mp_ptrs[] or node headers */
+ key.mv_size = nsize = mp->mp_pad;
+ key.mv_data = LEAF2KEY(mp, i, nsize);
+ total += nsize;
+ fprintf(stderr, "key %d: nsize %d, %s\n", i, nsize, DKEY(&key));
+ continue;
+ }
node = NODEPTR(mp, i);
key.mv_size = node->mn_ksize;
key.mv_data = node->mn_data;
nsize += NODEDSZ(node);
total += nsize;
nsize += sizeof(indx_t);
- fprintf(stderr, "key %d: nsize %d, %s\n", i, nsize, DKEY(&key));
+ fprintf(stderr, "key %d: nsize %d, %s%s\n",
+ i, nsize, DKEY(&key), mdb_leafnode_type(node));
}
total = EVEN(total);
}
- fprintf(stderr, "Total: %d\n", total);
+ fprintf(stderr, "Total: header %d + contents %d + unused %d\n",
+ IS_LEAF2(mp) ? PAGEHDRSZ : mp->mp_lower, total, SIZELEFT(mp));
}
void
/** Count all the pages in each DB and in the freelist
* and make sure it matches the actual number of pages
* being used.
+ * All named DBs must be open for a correct count.
*/
static void mdb_audit(MDB_txn *txn)
{
mdb_cursor_init(&mc, txn, FREE_DBI, NULL);
while ((rc = mdb_cursor_get(&mc, &key, &data, MDB_NEXT)) == 0)
freecount += *(MDB_ID *)data.mv_data;
+ mdb_tassert(txn, rc == MDB_NOTFOUND);
count = 0;
for (i = 0; i<txn->mt_numdbs; i++) {
MDB_xcursor mx;
+ if (!(txn->mt_dbflags[i] & DB_VALID))
+ continue;
mdb_cursor_init(&mc, txn, i, &mx);
if (txn->mt_dbs[i].md_root == P_INVALID)
continue;
txn->mt_dbs[i].md_leaf_pages +
txn->mt_dbs[i].md_overflow_pages;
if (txn->mt_dbs[i].md_flags & MDB_DUPSORT) {
- mdb_page_search(&mc, NULL, MDB_PS_FIRST);
- do {
+ rc = mdb_page_search(&mc, NULL, MDB_PS_FIRST);
+ for (; rc == MDB_SUCCESS; rc = mdb_cursor_sibling(&mc, 1)) {
unsigned j;
MDB_page *mp;
mp = mc.mc_pg[mc.mc_top];
}
}
}
- while (mdb_cursor_sibling(&mc, 1) == 0);
+ mdb_tassert(txn, rc == MDB_NOTFOUND);
}
}
if (freecount + count + 2 /* metapages */ != txn->mt_next_pgno) {
if (m2->mc_pg[mc->mc_top] == mp) {
m2->mc_pg[mc->mc_top] = np;
if ((mc->mc_db->md_flags & MDB_DUPSORT) &&
+ IS_LEAF(np) &&
m2->mc_ki[mc->mc_top] == mc->mc_ki[mc->mc_top])
{
MDB_node *leaf = NODEPTR(np, mc->mc_ki[mc->mc_top]);
MDB_PID_T pid = env->me_pid;
pthread_t tid = pthread_self();
- if (!(env->me_flags & MDB_LIVE_READER)) {
+ if (!env->me_live_reader) {
rc = mdb_reader_pid(env, Pidset, pid);
if (rc)
return rc;
- env->me_flags |= MDB_LIVE_READER;
+ env->me_live_reader = 1;
}
LOCK_MUTEX_R(env);
MDB_ID save;
mdb_tassert(txn, len >= 0 && id <= env->me_pglast);
- key.mv_data = &id;
if (len > mop_len) {
len = mop_len;
data.mv_size = (len + 1) * sizeof(MDB_ID);
+ /* Drop MDB_CURRENT when changing the data size */
+ key.mv_data = &id;
flags = 0;
}
data.mv_data = mop -= len;
int exact = 0;
DKBUF;
- if (key == NULL || data == NULL)
- return EINVAL;
-
DPRINTF(("===> get db %u key [%s]", dbi, DKEY(key)));
- if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
+ if (!key || !data || dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
return EINVAL;
if (txn->mt_flags & MDB_TXN_ERROR)
unsigned int nflags;
DKBUF;
- if (mc == NULL || key == NULL)
+ if (mc == NULL)
return EINVAL;
env = mc->mc_txn->mt_env;
if (mc->mc_txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_ERROR))
return (mc->mc_txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
- if (flags != MDB_CURRENT && key->mv_size-1 >= ENV_MAXKEY(env))
- return MDB_BAD_VALSIZE;
+ if (flags != MDB_CURRENT) {
+ if (key == NULL)
+ return EINVAL;
+ if (key->mv_size-1 >= ENV_MAXKEY(env))
+ return MDB_BAD_VALSIZE;
+ } else {
+ /* Ignore key except in sub-cursor, where key holds the data */
+ if (!(mc->mc_flags & C_SUB))
+ key = NULL;
+ }
#if SIZE_MAX > MAXDATASIZE
if (data->mv_size > ((mc->mc_db->md_flags & MDB_DUPSORT) ? ENV_MAXKEY(env) : MAXDATASIZE))
*/
if (F_ISSET(flags, MDB_RESERVE))
data->mv_data = olddata.mv_data;
- else if (data->mv_size)
+ else if (!(mc->mc_flags & C_SUB))
memcpy(olddata.mv_data, data->mv_data, data->mv_size);
else
memcpy(NODEKEY(leaf), key->mv_data, key->mv_size);
/* converted, write the original data first */
if (dkey.mv_size) {
rc = mdb_cursor_put(&mc->mc_xcursor->mx_cursor, &dkey, &xdata, xflags);
- if (rc)
- return rc;
+ if (rc) {
+ mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
+ return rc == MDB_KEYEXIST ? MDB_CORRUPTED : rc;
+ }
{
/* Adjust other cursors pointing to mp */
MDB_cursor *m2;
return rc;
mp = mc->mc_pg[mc->mc_top];
+ if (IS_LEAF2(mp))
+ goto del_key;
leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
- if (!IS_LEAF2(mp) && F_ISSET(leaf->mn_flags, F_DUPDATA)) {
+ if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
if (!(flags & MDB_NODUPDATA)) {
if (!F_ISSET(leaf->mn_flags, F_SUBDATA)) {
mc->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf);
}
rc = mdb_cursor_del(&mc->mc_xcursor->mx_cursor, MDB_NOSPILL);
+ if (rc)
+ return rc;
/* If sub-DB still has entries, we're done */
if (mc->mc_xcursor->mx_db.md_entries) {
if (leaf->mn_flags & F_SUBDATA) {
if (leaf->mn_flags & F_SUBDATA) {
/* add all the child DB's pages to the free list */
rc = mdb_drop0(&mc->mc_xcursor->mx_cursor, 0);
- if (rc == MDB_SUCCESS) {
- mc->mc_db->md_entries -=
- mc->mc_xcursor->mx_db.md_entries;
- }
+ if (rc)
+ goto fail;
+ mc->mc_db->md_entries -= mc->mc_xcursor->mx_db.md_entries;
}
}
- return mdb_cursor_del0(mc, leaf);
+ /* add overflow pages to free list */
+ if (F_ISSET(leaf->mn_flags, F_BIGDATA)) {
+ MDB_page *omp;
+ pgno_t pg;
+
+ memcpy(&pg, NODEDATA(leaf), sizeof(pg));
+ if ((rc = mdb_page_get(mc->mc_txn, pg, &omp, NULL)) ||
+ (rc = mdb_ovpage_free(mc, omp)))
+ goto fail;
+ }
+
+del_key:
+ return mdb_cursor_del0(mc);
+
+fail:
+ mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
+ return rc;
}
/** Allocate and initialize new pages for a database.
}
/** Delete the specified node from a page.
- * @param[in] mp The page to operate on.
- * @param[in] indx The index of the node to delete.
+ * @param[in] mc Cursor pointing to the node to delete.
* @param[in] ksize The size of a node. Only used if the page is
* part of a #MDB_DUPFIXED database.
*/
MDB_cursor *mc;
size_t size = sizeof(MDB_cursor);
- if (txn == NULL || ret == NULL || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
+ if (!ret || !TXN_DBI_EXIST(txn, dbi))
return EINVAL;
if (txn->mt_flags & MDB_TXN_ERROR)
int
mdb_cursor_renew(MDB_txn *txn, MDB_cursor *mc)
{
- if (txn == NULL || mc == NULL || mc->mc_dbi >= txn->mt_numdbs)
+ if (!mc || !TXN_DBI_EXIST(txn, mc->mc_dbi))
return EINVAL;
if ((mc->mc_flags & C_UNTRACK) || txn->mt_cursors)
return EINVAL;
+ if (txn->mt_flags & MDB_TXN_ERROR)
+ return MDB_BAD_TXN;
+
mdb_cursor_init(mc, txn, mc->mc_dbi, mc->mc_xcursor);
return MDB_SUCCESS;
}
if (mc->mc_xcursor == NULL)
return MDB_INCOMPATIBLE;
+ if (mc->mc_txn->mt_flags & MDB_TXN_ERROR)
+ return MDB_BAD_TXN;
+
leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) {
*countp = 1;
unsigned int snum = csrc->mc_snum;
MDB_node *s2;
/* must find the lowest key below src */
- mdb_page_search_lowest(csrc);
+ rc = mdb_page_search_lowest(csrc);
+ if (rc)
+ return rc;
if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
key.mv_size = csrc->mc_db->md_pad;
key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.mv_size);
MDB_node *s2;
MDB_val bkey;
/* must find the lowest key below dst */
- mdb_page_search_lowest(cdst);
+ rc = mdb_page_search_lowest(cdst);
+ if (rc)
+ return rc;
if (IS_LEAF2(cdst->mc_pg[cdst->mc_top])) {
bkey.mv_size = cdst->mc_db->md_pad;
bkey.mv_data = LEAF2KEY(cdst->mc_pg[cdst->mc_top], 0, bkey.mv_size);
* the \b csrc page will be freed.
* @param[in] csrc Cursor pointing to the source page.
* @param[in] cdst Cursor pointing to the destination page.
+ * @return 0 on success, non-zero on failure.
*/
static int
mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
unsigned int snum = csrc->mc_snum;
MDB_node *s2;
/* must find the lowest key below src */
- mdb_page_search_lowest(csrc);
+ rc = mdb_page_search_lowest(csrc);
+ if (rc)
+ return rc;
if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
key.mv_size = csrc->mc_db->md_pad;
key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.mv_size);
/** Complete a delete operation started by #mdb_cursor_del(). */
static int
-mdb_cursor_del0(MDB_cursor *mc, MDB_node *leaf)
+mdb_cursor_del0(MDB_cursor *mc)
{
int rc;
MDB_page *mp;
indx_t ki;
unsigned int nkeys;
- mp = mc->mc_pg[mc->mc_top];
ki = mc->mc_ki[mc->mc_top];
-
- /* add overflow pages to free list */
- if (!IS_LEAF2(mp) && F_ISSET(leaf->mn_flags, F_BIGDATA)) {
- MDB_page *omp;
- pgno_t pg;
-
- memcpy(&pg, NODEDATA(leaf), sizeof(pg));
- if ((rc = mdb_page_get(mc->mc_txn, pg, &omp, NULL)) ||
- (rc = mdb_ovpage_free(mc, omp)))
- return rc;
- }
mdb_node_del(mc, mc->mc_db->md_pad);
mc->mc_db->md_entries--;
rc = mdb_rebalance(mc);
- if (rc != MDB_SUCCESS)
- mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
- else {
+
+ if (rc == MDB_SUCCESS) {
MDB_cursor *m2, *m3;
MDB_dbi dbi = mc->mc_dbi;
nkeys = NUMKEYS(mp);
/* if mc points past last node in page, find next sibling */
- if (mc->mc_ki[mc->mc_top] >= nkeys)
- mdb_cursor_sibling(mc, 1);
+ if (mc->mc_ki[mc->mc_top] >= nkeys) {
+ rc = mdb_cursor_sibling(mc, 1);
+ if (rc == MDB_NOTFOUND)
+ rc = MDB_SUCCESS;
+ }
/* Adjust other cursors pointing to mp */
- for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) {
+ for (m2 = mc->mc_txn->mt_cursors[dbi]; !rc && m2; m2=m2->mc_next) {
m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2;
if (! (m2->mc_flags & m3->mc_flags & C_INITIALIZED))
continue;
if (m3->mc_ki[mc->mc_top] > ki)
m3->mc_ki[mc->mc_top]--;
}
- if (m3->mc_ki[mc->mc_top] >= nkeys)
- mdb_cursor_sibling(m3, 1);
+ if (m3->mc_ki[mc->mc_top] >= nkeys) {
+ rc = mdb_cursor_sibling(m3, 1);
+ if (rc == MDB_NOTFOUND)
+ rc = MDB_SUCCESS;
+ }
}
}
mc->mc_flags |= C_DEL;
}
+ if (rc)
+ mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
return rc;
}
int
mdb_del(MDB_txn *txn, MDB_dbi dbi,
MDB_val *key, MDB_val *data)
+{
+ if (!key || dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
+ return EINVAL;
+
+ if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_ERROR))
+ return (txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
+
+ if (!F_ISSET(txn->mt_dbs[dbi].md_flags, MDB_DUPSORT)) {
+ /* must ignore any data */
+ data = NULL;
+ }
+
+ return mdb_del0(txn, dbi, key, data, 0);
+}
+
+static int
+mdb_del0(MDB_txn *txn, MDB_dbi dbi,
+ MDB_val *key, MDB_val *data, unsigned flags)
{
MDB_cursor mc;
MDB_xcursor mx;
MDB_cursor_op op;
MDB_val rdata, *xdata;
- int rc, exact;
+ int rc, exact = 0;
DKBUF;
- if (key == NULL)
- return EINVAL;
-
DPRINTF(("====> delete db %u key [%s]", dbi, DKEY(key)));
- if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
- return EINVAL;
-
- if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_ERROR))
- return (txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
-
mdb_cursor_init(&mc, txn, dbi, &mx);
- exact = 0;
- if (!F_ISSET(txn->mt_dbs[dbi].md_flags, MDB_DUPSORT)) {
- /* must ignore any data */
- data = NULL;
- }
if (data) {
op = MDB_GET_BOTH;
rdata = *data;
} else {
op = MDB_SET;
xdata = NULL;
+ flags |= MDB_NODUPDATA;
}
rc = mdb_cursor_set(&mc, key, xdata, op, &exact);
if (rc == 0) {
mc.mc_flags |= C_UNTRACK;
mc.mc_next = txn->mt_cursors[dbi];
txn->mt_cursors[dbi] = &mc;
- rc = mdb_cursor_del(&mc, data ? 0 : MDB_NODUPDATA);
+ rc = mdb_cursor_del(&mc, flags);
txn->mt_cursors[dbi] = mc.mc_next;
}
return rc;
if (mc->mc_snum < 2) {
if ((rc = mdb_page_new(mc, P_BRANCH, 1, &pp)))
- return rc;
+ goto done;
/* shift current top to make room for new parent */
mc->mc_pg[1] = mc->mc_pg[0];
mc->mc_ki[1] = mc->mc_ki[0];
mc->mc_ki[0] = mc->mc_ki[1];
mc->mc_db->md_root = mp->mp_pgno;
mc->mc_db->md_depth--;
- return rc;
+ goto done;
}
mc->mc_snum = 2;
mc->mc_top = 1;
int x;
unsigned int lsize, rsize, ksize;
/* Move half of the keys to the right sibling */
- copy = NULL;
x = mc->mc_ki[mc->mc_top] - split_indx;
ksize = mc->mc_db->md_pad;
split = LEAF2KEY(mp, split_indx, ksize);
/* grab a page to hold a temporary copy */
copy = mdb_page_malloc(mc->mc_txn, 1);
- if (copy == NULL)
- return ENOMEM;
+ if (copy == NULL) {
+ rc = ENOMEM;
+ goto done;
+ }
copy->mp_pgno = mp->mp_pgno;
copy->mp_flags = mp->mp_flags;
copy->mp_lower = PAGEHDRSZ;
mn.mc_top--;
did_split = 1;
rc = mdb_page_split(&mn, &sepkey, NULL, rp->mp_pgno, 0);
+ if (rc)
+ goto done;
/* root split? */
if (mn.mc_snum == mc->mc_snum) {
mc->mc_ki[i] = mn.mc_ki[i];
}
mc->mc_pg[ptop] = mn.mc_pg[ptop];
- mc->mc_ki[ptop] = mn.mc_ki[ptop] - 1;
+ if (mn.mc_ki[ptop]) {
+ mc->mc_ki[ptop] = mn.mc_ki[ptop] - 1;
+ } else {
+ /* find right page's left sibling */
+ mc->mc_ki[ptop] = mn.mc_ki[ptop];
+ mdb_cursor_sibling(mc, 0);
+ }
}
} else {
mn.mc_top--;
}
mc->mc_flags ^= C_SPLITTING;
if (rc != MDB_SUCCESS) {
- return rc;
+ goto done;
}
if (nflags & MDB_APPEND) {
mc->mc_pg[mc->mc_top] = rp;
mc->mc_ki[mc->mc_top] = 0;
rc = mdb_node_add(mc, 0, newkey, newdata, newpgno, nflags);
if (rc)
- return rc;
+ goto done;
for (i=0; i<mc->mc_top; i++)
mc->mc_ki[i] = mn.mc_ki[i];
} else if (!IS_LEAF2(mp)) {
}
rc = mdb_node_add(mc, j, &rkey, rdata, pgno, flags);
- if (rc) {
- /* return tmp page to freelist */
- mdb_page_free(env, copy);
- return rc;
- }
+ if (rc)
+ goto done;
if (i == nkeys) {
i = 0;
j = 0;
*/
if (mn.mc_pg[ptop] != mc->mc_pg[ptop] &&
mc->mc_ki[ptop] >= NUMKEYS(mc->mc_pg[ptop])) {
- for (i=0; i<ptop; i++) {
+ for (i=0; i<=ptop; i++) {
mc->mc_pg[i] = mn.mc_pg[i];
mc->mc_ki[i] = mn.mc_ki[i];
}
- mc->mc_pg[ptop] = mn.mc_pg[ptop];
- mc->mc_ki[ptop] = mn.mc_ki[ptop] - 1;
}
}
- /* return tmp page to freelist */
- mdb_page_free(env, copy);
}
{
}
}
DPRINTF(("mp left: %d, rp left: %d", SIZELEFT(mp), SIZELEFT(rp)));
+
+done:
+ if (copy) /* tmp page */
+ mdb_page_free(env, copy);
+ if (rc)
+ mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
return rc;
}
MDB_cursor mc;
MDB_xcursor mx;
- if (key == NULL || data == NULL)
- return EINVAL;
-
- if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
+ if (!key || !data || dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
return EINVAL;
if ((flags & (MDB_NOOVERWRITE|MDB_NODUPDATA|MDB_RESERVE|MDB_APPEND|MDB_APPENDDUP)) != flags)
int mdb_stat(MDB_txn *txn, MDB_dbi dbi, MDB_stat *arg)
{
- if (txn == NULL || arg == NULL || dbi >= txn->mt_numdbs)
+ if (!arg || !TXN_DBI_EXIST(txn, dbi))
return EINVAL;
+ if (txn->mt_flags & MDB_TXN_ERROR)
+ return MDB_BAD_TXN;
+
if (txn->mt_dbflags[dbi] & DB_STALE) {
MDB_cursor mc;
MDB_xcursor mx;
int mdb_dbi_flags(MDB_txn *txn, MDB_dbi dbi, unsigned int *flags)
{
/* We could return the flags for the FREE_DBI too but what's the point? */
- if (txn == NULL || dbi < MAIN_DBI || dbi >= txn->mt_numdbs)
+ if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
return EINVAL;
*flags = txn->mt_dbs[dbi].md_flags & PERSISTENT_FLAGS;
return MDB_SUCCESS;
memcpy(&pg, NODEDATA(ni), sizeof(pg));
rc = mdb_page_get(txn, pg, &omp, NULL);
if (rc != 0)
- return rc;
+ goto done;
mdb_cassert(mc, IS_OVERFLOW(omp));
rc = mdb_midl_append_range(&txn->mt_free_pgs,
pg, omp->mp_pages);
if (rc)
- return rc;
+ goto done;
} else if (subs && (ni->mn_flags & F_SUBDATA)) {
mdb_xcursor_init1(mc, ni);
rc = mdb_drop0(&mc->mc_xcursor->mx_cursor, 0);
if (rc)
- return rc;
+ goto done;
}
}
} else {
if ((rc = mdb_midl_need(&txn->mt_free_pgs, n)) != 0)
- return rc;
+ goto done;
for (i=0; i<n; i++) {
pgno_t pg;
ni = NODEPTR(mp, i);
mc->mc_ki[mc->mc_top] = i;
rc = mdb_cursor_sibling(mc, 1);
if (rc) {
+ if (rc != MDB_NOTFOUND)
+ goto done;
/* no more siblings, go back to beginning
* of previous level.
*/
}
/* free it */
rc = mdb_midl_append(&txn->mt_free_pgs, mc->mc_db->md_root);
+done:
+ if (rc)
+ txn->mt_flags |= MDB_TXN_ERROR;
} else if (rc == MDB_NOTFOUND) {
rc = MDB_SUCCESS;
}
MDB_cursor *mc, *m2;
int rc;
- if (!txn || !dbi || dbi >= txn->mt_numdbs || (unsigned)del > 1 || !(txn->mt_dbflags[dbi] & DB_VALID))
+ if ((unsigned)del > 1 || dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
return EINVAL;
if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY))
/* Can't delete the main DB */
if (del && dbi > MAIN_DBI) {
- rc = mdb_del(txn, MAIN_DBI, &mc->mc_dbx->md_name, NULL);
+ rc = mdb_del0(txn, MAIN_DBI, &mc->mc_dbx->md_name, NULL, 0);
if (!rc) {
txn->mt_dbflags[dbi] = DB_STALE;
mdb_dbi_close(txn->mt_env, dbi);
+ } else {
+ txn->mt_flags |= MDB_TXN_ERROR;
}
} else {
/* reset the DB record, mark it dirty */
int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
{
- if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
+ if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
return EINVAL;
txn->mt_dbxs[dbi].md_cmp = cmp;
int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
{
- if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
+ if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
return EINVAL;
txn->mt_dbxs[dbi].md_dcmp = cmp;
int mdb_set_relfunc(MDB_txn *txn, MDB_dbi dbi, MDB_rel_func *rel)
{
- if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
+ if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
return EINVAL;
txn->mt_dbxs[dbi].md_rel = rel;
int mdb_set_relctx(MDB_txn *txn, MDB_dbi dbi, void *ctx)
{
- if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
+ if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
return EINVAL;
txn->mt_dbxs[dbi].md_relctx = ctx;
#include <time.h>
#include "lmdb.h"
+#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
+#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0))
+#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
+ "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))
+
int main(int argc,char * argv[])
{
int i = 0, j = 0, rc;
MDB_txn *txn;
MDB_stat mst;
MDB_cursor *cursor, *cur2;
+ MDB_cursor_op op;
int count;
int *values;
char sval[32] = "";
values[i] = random()%1024;
}
- rc = mdb_env_create(&env);
- rc = mdb_env_set_mapsize(env, 10485760);
- rc = mdb_env_open(env, "./testdb", MDB_FIXEDMAP /*|MDB_NOSYNC*/, 0664);
- rc = mdb_txn_begin(env, NULL, 0, &txn);
- rc = mdb_open(txn, NULL, 0, &dbi);
+ E(mdb_env_create(&env));
+ E(mdb_env_set_mapsize(env, 10485760));
+ E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP /*|MDB_NOSYNC*/, 0664));
+ E(mdb_txn_begin(env, NULL, 0, &txn));
+ E(mdb_open(txn, NULL, 0, &dbi));
key.mv_size = sizeof(int);
key.mv_data = sval;
printf("Adding %d values\n", count);
for (i=0;i<count;i++) {
sprintf(sval, "%03x %d foo bar", values[i], values[i]);
- rc = mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE);
- if (rc) {
+ if (RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE))) {
j++;
data.mv_size = sizeof(sval);
data.mv_data = sval;
}
}
if (j) printf("%d duplicates skipped\n", j);
- rc = mdb_txn_commit(txn);
- rc = mdb_env_stat(env, &mst);
+ E(mdb_txn_commit(txn));
+ E(mdb_env_stat(env, &mst));
- rc = mdb_txn_begin(env, NULL, 1, &txn);
- rc = mdb_cursor_open(txn, dbi, &cursor);
+ E(mdb_txn_begin(env, NULL, 1, &txn));
+ E(mdb_cursor_open(txn, dbi, &cursor));
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
printf("key: %p %.*s, data: %p %.*s\n",
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
mdb_cursor_close(cursor);
mdb_txn_abort(txn);
for (i= count - 1; i > -1; i-= (random()%5)) {
j++;
txn=NULL;
- rc = mdb_txn_begin(env, NULL, 0, &txn);
+ E(mdb_txn_begin(env, NULL, 0, &txn));
sprintf(sval, "%03x ", values[i]);
- rc = mdb_del(txn, dbi, &key, NULL);
- if (rc) {
+ if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, NULL))) {
j--;
mdb_txn_abort(txn);
} else {
- rc = mdb_txn_commit(txn);
+ E(mdb_txn_commit(txn));
}
}
free(values);
printf("Deleted %d values\n", j);
- rc = mdb_env_stat(env, &mst);
- rc = mdb_txn_begin(env, NULL, 1, &txn);
- rc = mdb_cursor_open(txn, dbi, &cursor);
+ E(mdb_env_stat(env, &mst));
+ E(mdb_txn_begin(env, NULL, 1, &txn));
+ E(mdb_cursor_open(txn, dbi, &cursor));
printf("Cursor next\n");
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
printf("key: %.*s, data: %.*s\n",
(int) key.mv_size, (char *) key.mv_data,
(int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
printf("Cursor last\n");
- rc = mdb_cursor_get(cursor, &key, &data, MDB_LAST);
+ E(mdb_cursor_get(cursor, &key, &data, MDB_LAST));
printf("key: %.*s, data: %.*s\n",
(int) key.mv_size, (char *) key.mv_data,
(int) data.mv_size, (char *) data.mv_data);
(int) key.mv_size, (char *) key.mv_data,
(int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
printf("Cursor last/prev\n");
- rc = mdb_cursor_get(cursor, &key, &data, MDB_LAST);
+ E(mdb_cursor_get(cursor, &key, &data, MDB_LAST));
printf("key: %.*s, data: %.*s\n",
(int) key.mv_size, (char *) key.mv_data,
(int) data.mv_size, (char *) data.mv_data);
- rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV);
+ E(mdb_cursor_get(cursor, &key, &data, MDB_PREV));
printf("key: %.*s, data: %.*s\n",
(int) key.mv_size, (char *) key.mv_data,
(int) data.mv_size, (char *) data.mv_data);
mdb_txn_abort(txn);
printf("Deleting with cursor\n");
- rc = mdb_txn_begin(env, NULL, 0, &txn);
- rc = mdb_cursor_open(txn, dbi, &cur2);
+ E(mdb_txn_begin(env, NULL, 0, &txn));
+ E(mdb_cursor_open(txn, dbi, &cur2));
for (i=0; i<50; i++) {
- rc = mdb_cursor_get(cur2, &key, &data, MDB_NEXT);
- if (rc)
+ if (RES(MDB_NOTFOUND, mdb_cursor_get(cur2, &key, &data, MDB_NEXT)))
break;
printf("key: %p %.*s, data: %p %.*s\n",
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
- rc = mdb_del(txn, dbi, &key, NULL);
+ E(mdb_del(txn, dbi, &key, NULL));
}
printf("Restarting cursor in txn\n");
- rc = mdb_cursor_get(cur2, &key, &data, MDB_FIRST);
- printf("key: %p %.*s, data: %p %.*s\n",
- key.mv_data, (int) key.mv_size, (char *) key.mv_data,
- data.mv_data, (int) data.mv_size, (char *) data.mv_data);
- for (i=0; i<32; i++) {
- rc = mdb_cursor_get(cur2, &key, &data, MDB_NEXT);
- if (rc) break;
+ for (op=MDB_FIRST, i=0; i<=32; op=MDB_NEXT, i++) {
+ if (RES(MDB_NOTFOUND, mdb_cursor_get(cur2, &key, &data, op)))
+ break;
printf("key: %p %.*s, data: %p %.*s\n",
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
}
mdb_cursor_close(cur2);
- rc = mdb_txn_commit(txn);
+ E(mdb_txn_commit(txn));
printf("Restarting cursor outside txn\n");
- rc = mdb_txn_begin(env, NULL, 0, &txn);
- rc = mdb_cursor_open(txn, dbi, &cursor);
- rc = mdb_cursor_get(cursor, &key, &data, MDB_FIRST);
- printf("key: %p %.*s, data: %p %.*s\n",
- key.mv_data, (int) key.mv_size, (char *) key.mv_data,
- data.mv_data, (int) data.mv_size, (char *) data.mv_data);
- for (i=0; i<32; i++) {
- rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT);
- if (rc) break;
+ E(mdb_txn_begin(env, NULL, 0, &txn));
+ E(mdb_cursor_open(txn, dbi, &cursor));
+ for (op=MDB_FIRST, i=0; i<=32; op=MDB_NEXT, i++) {
+ if (RES(MDB_NOTFOUND, mdb_cursor_get(cursor, &key, &data, op)))
+ break;
printf("key: %p %.*s, data: %p %.*s\n",
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
#include <time.h>
#include "lmdb.h"
+#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
+#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0))
+#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
+ "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))
+
int main(int argc,char * argv[])
{
int i = 0, j = 0, rc;
values[i] = random()%1024;
}
- rc = mdb_env_create(&env);
- rc = mdb_env_set_mapsize(env, 10485760);
- rc = mdb_env_set_maxdbs(env, 4);
- rc = mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664);
- rc = mdb_txn_begin(env, NULL, 0, &txn);
- rc = mdb_open(txn, "id1", MDB_CREATE, &dbi);
+ E(mdb_env_create(&env));
+ E(mdb_env_set_mapsize(env, 10485760));
+ E(mdb_env_set_maxdbs(env, 4));
+ E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664));
+ E(mdb_txn_begin(env, NULL, 0, &txn));
+ E(mdb_open(txn, "id1", MDB_CREATE, &dbi));
key.mv_size = sizeof(int);
key.mv_data = sval;
printf("Adding %d values\n", count);
for (i=0;i<count;i++) {
sprintf(sval, "%03x %d foo bar", values[i], values[i]);
- rc = mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE);
- if (rc) j++;
+ if (RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE)))
+ j++;
}
if (j) printf("%d duplicates skipped\n", j);
- rc = mdb_txn_commit(txn);
- rc = mdb_env_stat(env, &mst);
+ E(mdb_txn_commit(txn));
+ E(mdb_env_stat(env, &mst));
- rc = mdb_txn_begin(env, NULL, 1, &txn);
- rc = mdb_cursor_open(txn, dbi, &cursor);
+ E(mdb_txn_begin(env, NULL, 1, &txn));
+ E(mdb_cursor_open(txn, dbi, &cursor));
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
printf("key: %p %.*s, data: %p %.*s\n",
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
mdb_cursor_close(cursor);
mdb_txn_abort(txn);
for (i= count - 1; i > -1; i-= (random()%5)) {
j++;
txn=NULL;
- rc = mdb_txn_begin(env, NULL, 0, &txn);
+ E(mdb_txn_begin(env, NULL, 0, &txn));
sprintf(sval, "%03x ", values[i]);
- rc = mdb_del(txn, dbi, &key, NULL);
- if (rc) {
+ if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, NULL))) {
j--;
mdb_txn_abort(txn);
} else {
- rc = mdb_txn_commit(txn);
+ E(mdb_txn_commit(txn));
}
}
free(values);
printf("Deleted %d values\n", j);
- rc = mdb_env_stat(env, &mst);
- rc = mdb_txn_begin(env, NULL, 1, &txn);
- rc = mdb_cursor_open(txn, dbi, &cursor);
+ E(mdb_env_stat(env, &mst));
+ E(mdb_txn_begin(env, NULL, 1, &txn));
+ E(mdb_cursor_open(txn, dbi, &cursor));
printf("Cursor next\n");
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
printf("key: %.*s, data: %.*s\n",
(int) key.mv_size, (char *) key.mv_data,
(int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
printf("Cursor prev\n");
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) {
printf("key: %.*s, data: %.*s\n",
(int) key.mv_size, (char *) key.mv_data,
(int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
mdb_cursor_close(cursor);
mdb_close(env, dbi);
#include <time.h>
#include "lmdb.h"
+#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
+#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0))
+#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
+ "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))
+
int main(int argc,char * argv[])
{
int i = 0, j = 0, rc;
values[i] = random()%1024;
}
- rc = mdb_env_create(&env);
- rc = mdb_env_set_mapsize(env, 10485760);
- rc = mdb_env_set_maxdbs(env, 4);
- rc = mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664);
- rc = mdb_txn_begin(env, NULL, 0, &txn);
- rc = mdb_open(txn, "id2", MDB_CREATE|MDB_DUPSORT, &dbi);
+ E(mdb_env_create(&env));
+ E(mdb_env_set_mapsize(env, 10485760));
+ E(mdb_env_set_maxdbs(env, 4));
+ E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664));
+ E(mdb_txn_begin(env, NULL, 0, &txn));
+ E(mdb_open(txn, "id2", MDB_CREATE|MDB_DUPSORT, &dbi));
key.mv_size = sizeof(int);
key.mv_data = kval;
if (!(i & 0x0f))
sprintf(kval, "%03x", values[i]);
sprintf(sval, "%03x %d foo bar", values[i], values[i]);
- rc = mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA);
- if (rc) j++;
+ if (RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA)))
+ j++;
}
if (j) printf("%d duplicates skipped\n", j);
- rc = mdb_txn_commit(txn);
- rc = mdb_env_stat(env, &mst);
+ E(mdb_txn_commit(txn));
+ E(mdb_env_stat(env, &mst));
- rc = mdb_txn_begin(env, NULL, 1, &txn);
- rc = mdb_cursor_open(txn, dbi, &cursor);
+ E(mdb_txn_begin(env, NULL, 1, &txn));
+ E(mdb_cursor_open(txn, dbi, &cursor));
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
printf("key: %p %.*s, data: %p %.*s\n",
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
mdb_cursor_close(cursor);
mdb_txn_abort(txn);
for (i= count - 1; i > -1; i-= (random()%5)) {
j++;
txn=NULL;
- rc = mdb_txn_begin(env, NULL, 0, &txn);
+ E(mdb_txn_begin(env, NULL, 0, &txn));
sprintf(kval, "%03x", values[i & ~0x0f]);
sprintf(sval, "%03x %d foo bar", values[i], values[i]);
key.mv_size = sizeof(int);
key.mv_data = kval;
data.mv_size = sizeof(sval);
data.mv_data = sval;
- rc = mdb_del(txn, dbi, &key, &data);
- if (rc) {
+ if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) {
j--;
mdb_txn_abort(txn);
} else {
- rc = mdb_txn_commit(txn);
+ E(mdb_txn_commit(txn));
}
}
free(values);
printf("Deleted %d values\n", j);
- rc = mdb_env_stat(env, &mst);
- rc = mdb_txn_begin(env, NULL, 1, &txn);
- rc = mdb_cursor_open(txn, dbi, &cursor);
+ E(mdb_env_stat(env, &mst));
+ E(mdb_txn_begin(env, NULL, 1, &txn));
+ E(mdb_cursor_open(txn, dbi, &cursor));
printf("Cursor next\n");
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
printf("key: %.*s, data: %.*s\n",
(int) key.mv_size, (char *) key.mv_data,
(int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
printf("Cursor prev\n");
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) {
printf("key: %.*s, data: %.*s\n",
(int) key.mv_size, (char *) key.mv_data,
(int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
mdb_cursor_close(cursor);
mdb_close(env, dbi);
#include <time.h>
#include "lmdb.h"
+#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
+#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0))
+#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
+ "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))
+
int main(int argc,char * argv[])
{
int i = 0, j = 0, rc;
values[i] = i*5;
}
- rc = mdb_env_create(&env);
- rc = mdb_env_set_mapsize(env, 10485760);
- rc = mdb_env_set_maxdbs(env, 4);
- rc = mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664);
- rc = mdb_txn_begin(env, NULL, 0, &txn);
- rc = mdb_open(txn, "id2", MDB_CREATE|MDB_DUPSORT|MDB_DUPFIXED, &dbi);
+ E(mdb_env_create(&env));
+ E(mdb_env_set_mapsize(env, 10485760));
+ E(mdb_env_set_maxdbs(env, 4));
+ E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664));
+ E(mdb_txn_begin(env, NULL, 0, &txn));
+ E(mdb_open(txn, "id4", MDB_CREATE|MDB_DUPSORT|MDB_DUPFIXED, &dbi));
key.mv_size = sizeof(int);
key.mv_data = kval;
strcpy(kval, "001");
for (i=0;i<count;i++) {
sprintf(sval, "%07x", values[i]);
- rc = mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA);
- if (rc) j++;
+ if (RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA)))
+ j++;
}
if (j) printf("%d duplicates skipped\n", j);
- rc = mdb_txn_commit(txn);
- rc = mdb_env_stat(env, &mst);
+ E(mdb_txn_commit(txn));
+ E(mdb_env_stat(env, &mst));
/* there should be one full page of dups now.
*/
- rc = mdb_txn_begin(env, NULL, 1, &txn);
- rc = mdb_cursor_open(txn, dbi, &cursor);
+ E(mdb_txn_begin(env, NULL, 1, &txn));
+ E(mdb_cursor_open(txn, dbi, &cursor));
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
printf("key: %p %.*s, data: %p %.*s\n",
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
mdb_cursor_close(cursor);
mdb_txn_abort(txn);
data.mv_data = sval;
sprintf(sval, "%07x", values[3]+1);
- rc = mdb_txn_begin(env, NULL, 0, &txn);
- rc = mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA);
+ E(mdb_txn_begin(env, NULL, 0, &txn));
+ (void)RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA));
mdb_txn_abort(txn);
sprintf(sval, "%07x", values[255]+1);
- rc = mdb_txn_begin(env, NULL, 0, &txn);
- rc = mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA);
+ E(mdb_txn_begin(env, NULL, 0, &txn));
+ (void)RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA));
mdb_txn_abort(txn);
sprintf(sval, "%07x", values[500]+1);
- rc = mdb_txn_begin(env, NULL, 0, &txn);
- rc = mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA);
- rc = mdb_txn_commit(txn);
+ E(mdb_txn_begin(env, NULL, 0, &txn));
+ (void)RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA));
+ E(mdb_txn_commit(txn));
/* Try MDB_NEXT_MULTIPLE */
- rc = mdb_txn_begin(env, NULL, 0, &txn);
- rc = mdb_cursor_open(txn, dbi, &cursor);
+ E(mdb_txn_begin(env, NULL, 0, &txn));
+ E(mdb_cursor_open(txn, dbi, &cursor));
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT_MULTIPLE)) == 0) {
printf("key: %.*s, data: %.*s\n",
(int) key.mv_size, (char *) key.mv_data,
(int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
mdb_cursor_close(cursor);
mdb_txn_abort(txn);
j=0;
for (i= count - 1; i > -1; i-= (random()%3)) {
j++;
txn=NULL;
- rc = mdb_txn_begin(env, NULL, 0, &txn);
+ E(mdb_txn_begin(env, NULL, 0, &txn));
sprintf(sval, "%07x", values[i]);
key.mv_size = sizeof(int);
key.mv_data = kval;
data.mv_size = sizeof(sval);
data.mv_data = sval;
- rc = mdb_del(txn, dbi, &key, &data);
- if (rc) {
+ if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) {
j--;
mdb_txn_abort(txn);
} else {
- rc = mdb_txn_commit(txn);
+ E(mdb_txn_commit(txn));
}
}
free(values);
printf("Deleted %d values\n", j);
- rc = mdb_env_stat(env, &mst);
- rc = mdb_txn_begin(env, NULL, 1, &txn);
- rc = mdb_cursor_open(txn, dbi, &cursor);
+ E(mdb_env_stat(env, &mst));
+ E(mdb_txn_begin(env, NULL, 1, &txn));
+ E(mdb_cursor_open(txn, dbi, &cursor));
printf("Cursor next\n");
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
printf("key: %.*s, data: %.*s\n",
(int) key.mv_size, (char *) key.mv_data,
(int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
printf("Cursor prev\n");
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) {
printf("key: %.*s, data: %.*s\n",
(int) key.mv_size, (char *) key.mv_data,
(int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
mdb_cursor_close(cursor);
mdb_close(env, dbi);
#include <time.h>
#include "lmdb.h"
+#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
+#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0))
+#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
+ "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))
+
int main(int argc,char * argv[])
{
int i = 0, j = 0, rc;
values[i] = random()%1024;
}
- rc = mdb_env_create(&env);
- rc = mdb_env_set_mapsize(env, 10485760);
- rc = mdb_env_set_maxdbs(env, 4);
- rc = mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664);
- rc = mdb_txn_begin(env, NULL, 0, &txn);
- rc = mdb_open(txn, "id2", MDB_CREATE|MDB_DUPSORT, &dbi);
- rc = mdb_cursor_open(txn, dbi, &cursor);
+ E(mdb_env_create(&env));
+ E(mdb_env_set_mapsize(env, 10485760));
+ E(mdb_env_set_maxdbs(env, 4));
+ E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664));
+ E(mdb_txn_begin(env, NULL, 0, &txn));
+ E(mdb_open(txn, "id2", MDB_CREATE|MDB_DUPSORT, &dbi));
+ E(mdb_cursor_open(txn, dbi, &cursor));
key.mv_size = sizeof(int);
key.mv_data = kval;
if (!(i & 0x0f))
sprintf(kval, "%03x", values[i]);
sprintf(sval, "%03x %d foo bar", values[i], values[i]);
- rc = mdb_cursor_put(cursor, &key, &data, MDB_NODUPDATA);
- if (rc) j++;
+ if (RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NODUPDATA)))
+ j++;
}
if (j) printf("%d duplicates skipped\n", j);
mdb_cursor_close(cursor);
- rc = mdb_txn_commit(txn);
- rc = mdb_env_stat(env, &mst);
+ E(mdb_txn_commit(txn));
+ E(mdb_env_stat(env, &mst));
- rc = mdb_txn_begin(env, NULL, 1, &txn);
- rc = mdb_cursor_open(txn, dbi, &cursor);
+ E(mdb_txn_begin(env, NULL, 1, &txn));
+ E(mdb_cursor_open(txn, dbi, &cursor));
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
printf("key: %p %.*s, data: %p %.*s\n",
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
mdb_cursor_close(cursor);
mdb_txn_abort(txn);
for (i= count - 1; i > -1; i-= (random()%5)) {
j++;
txn=NULL;
- rc = mdb_txn_begin(env, NULL, 0, &txn);
+ E(mdb_txn_begin(env, NULL, 0, &txn));
sprintf(kval, "%03x", values[i & ~0x0f]);
sprintf(sval, "%03x %d foo bar", values[i], values[i]);
key.mv_size = sizeof(int);
key.mv_data = kval;
data.mv_size = sizeof(sval);
data.mv_data = sval;
- rc = mdb_del(txn, dbi, &key, &data);
- if (rc) {
+ if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) {
j--;
mdb_txn_abort(txn);
} else {
- rc = mdb_txn_commit(txn);
+ E(mdb_txn_commit(txn));
}
}
free(values);
printf("Deleted %d values\n", j);
- rc = mdb_env_stat(env, &mst);
- rc = mdb_txn_begin(env, NULL, 1, &txn);
- rc = mdb_cursor_open(txn, dbi, &cursor);
+ E(mdb_env_stat(env, &mst));
+ E(mdb_txn_begin(env, NULL, 1, &txn));
+ E(mdb_cursor_open(txn, dbi, &cursor));
printf("Cursor next\n");
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
printf("key: %.*s, data: %.*s\n",
(int) key.mv_size, (char *) key.mv_data,
(int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
printf("Cursor prev\n");
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) {
printf("key: %.*s, data: %.*s\n",
(int) key.mv_size, (char *) key.mv_data,
(int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
mdb_cursor_close(cursor);
mdb_close(env, dbi);
#include <time.h>
#include "lmdb.h"
+#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
+#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0))
+#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
+ "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))
+
char dkbuf[1024];
int main(int argc,char * argv[])
srandom(time(NULL));
- rc = mdb_env_create(&env);
- rc = mdb_env_set_mapsize(env, 10485760);
- rc = mdb_env_set_maxdbs(env, 4);
- rc = mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664);
- rc = mdb_txn_begin(env, NULL, 0, &txn);
- rc = mdb_open(txn, "id2", MDB_CREATE|MDB_INTEGERKEY, &dbi);
- rc = mdb_cursor_open(txn, dbi, &cursor);
- rc = mdb_stat(txn, dbi, &mst);
+ E(mdb_env_create(&env));
+ E(mdb_env_set_mapsize(env, 10485760));
+ E(mdb_env_set_maxdbs(env, 4));
+ E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664));
+ E(mdb_txn_begin(env, NULL, 0, &txn));
+ E(mdb_open(txn, "id6", MDB_CREATE|MDB_INTEGERKEY, &dbi));
+ E(mdb_cursor_open(txn, dbi, &cursor));
+ E(mdb_stat(txn, dbi, &mst));
sval = calloc(1, mst.ms_psize / 4);
key.mv_size = sizeof(long);
for (i=0;i<12;i++) {
kval = i*5;
sprintf(sval, "%08x", kval);
- rc = mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE);
+ (void)RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE));
}
printf("Adding 12 more values, should yield 3 splits\n");
for (i=0;i<12;i++) {
kval = i*5+4;
sprintf(sval, "%08x", kval);
- rc = mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE);
+ (void)RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE));
}
printf("Adding 12 more values, should yield 3 splits\n");
for (i=0;i<12;i++) {
kval = i*5+1;
sprintf(sval, "%08x", kval);
- rc = mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE);
+ (void)RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE));
}
- rc = mdb_cursor_get(cursor, &key, &data, MDB_FIRST);
+ E(mdb_cursor_get(cursor, &key, &data, MDB_FIRST));
do {
printf("key: %p %s, data: %p %.*s\n",
key.mv_data, mdb_dkey(&key, dkbuf),
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
} while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0);
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
mdb_cursor_close(cursor);
mdb_txn_commit(txn);
for (i= count - 1; i > -1; i-= (random()%5)) {
j++;
txn=NULL;
- rc = mdb_txn_begin(env, NULL, 0, &txn);
+ E(mdb_txn_begin(env, NULL, 0, &txn));
sprintf(kval, "%03x", values[i & ~0x0f]);
sprintf(sval, "%03x %d foo bar", values[i], values[i]);
key.mv_size = sizeof(int);
key.mv_data = kval;
data.mv_size = sizeof(sval);
data.mv_data = sval;
- rc = mdb_del(txn, dbi, &key, &data);
- if (rc) {
+ if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) {
j--;
mdb_txn_abort(txn);
} else {
- rc = mdb_txn_commit(txn);
+ E(mdb_txn_commit(txn));
}
}
free(values);
printf("Deleted %d values\n", j);
- rc = mdb_env_stat(env, &mst);
- rc = mdb_txn_begin(env, NULL, 1, &txn);
- rc = mdb_cursor_open(txn, dbi, &cursor);
+ E(mdb_env_stat(env, &mst));
+ E(mdb_txn_begin(env, NULL, 1, &txn));
+ E(mdb_cursor_open(txn, dbi, &cursor));
printf("Cursor next\n");
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
printf("key: %.*s, data: %.*s\n",
(int) key.mv_size, (char *) key.mv_data,
(int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
printf("Cursor prev\n");
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) {
printf("key: %.*s, data: %.*s\n",
(int) key.mv_size, (char *) key.mv_data,
(int) data.mv_size, (char *) data.mv_data);
}
+ CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
mdb_cursor_close(cursor);
- mdb_close(txn, dbi);
+ mdb_close(env, dbi);
mdb_txn_abort(txn);
#endif
+++ /dev/null
-/* sample-bdb.c - BerkeleyDB toy/sample
- *
- * Do a line-by-line comparison of this and sample-mdb.c
- */
-/*
- * Copyright 2012 Howard Chu, Symas Corp.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-#include <stdio.h>
-#include <string.h>
-#include <db.h>
-
-int main(int argc,char * argv[])
-{
- int rc;
- DB_ENV *env;
- DB *dbi;
- DBT key, data;
- DB_TXN *txn;
- DBC *cursor;
- char sval[32], kval[32];
-
-#define FLAGS (DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_INIT_MPOOL|DB_CREATE|DB_THREAD)
- rc = db_env_create(&env, 0);
- rc = env->open(env, "./testdb", FLAGS, 0664);
- rc = db_create(&dbi, env, 0);
- rc = env->txn_begin(env, NULL, &txn, 0);
- rc = dbi->open(dbi, txn, "test.bdb", NULL, DB_BTREE, DB_CREATE, 0664);
-
- memset(&key, 0, sizeof(DBT));
- memset(&data, 0, sizeof(DBT));
- key.size = sizeof(int);
- key.data = sval;
- data.size = sizeof(sval);
- data.data = sval;
-
- sprintf(sval, "%03x %d foo bar", 32, 3141592);
- rc = dbi->put(dbi, txn, &key, &data, 0);
- rc = txn->commit(txn, 0);
- if (rc) {
- fprintf(stderr, "txn->commit: (%d) %s\n", rc, db_strerror(rc));
- goto leave;
- }
- rc = env->txn_begin(env, NULL, &txn, 0);
- rc = dbi->cursor(dbi, txn, &cursor, 0);
- key.flags = DB_DBT_USERMEM;
- key.data = kval;
- key.ulen = sizeof(kval);
- data.flags = DB_DBT_USERMEM;
- data.data = sval;
- data.ulen = sizeof(sval);
- while ((rc = cursor->c_get(cursor, &key, &data, DB_NEXT)) == 0) {
- printf("key: %p %.*s, data: %p %.*s\n",
- key.data, (int) key.size, (char *) key.data,
- data.data, (int) data.size, (char *) data.data);
- }
- rc = cursor->c_close(cursor);
- rc = txn->abort(txn);
-leave:
- rc = dbi->close(dbi, 0);
- rc = env->close(env, 0);
- return rc;
-}
--- /dev/null
+/* sample-bdb.txt - BerkeleyDB toy/sample
+ *
+ * Do a line-by-line comparison of this and sample-mdb.txt
+ */
+/*
+ * Copyright 2012 Howard Chu, Symas Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <db.h>
+
+int main(int argc,char * argv[])
+{
+ int rc;
+ DB_ENV *env;
+ DB *dbi;
+ DBT key, data;
+ DB_TXN *txn;
+ DBC *cursor;
+ char sval[32], kval[32];
+
+ /* Note: Most error checking omitted for simplicity */
+
+#define FLAGS (DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_INIT_MPOOL|DB_CREATE|DB_THREAD)
+ rc = db_env_create(&env, 0);
+ rc = env->open(env, "./testdb", FLAGS, 0664);
+ rc = db_create(&dbi, env, 0);
+ rc = env->txn_begin(env, NULL, &txn, 0);
+ rc = dbi->open(dbi, txn, "test.bdb", NULL, DB_BTREE, DB_CREATE, 0664);
+
+ memset(&key, 0, sizeof(DBT));
+ memset(&data, 0, sizeof(DBT));
+ key.size = sizeof(int);
+ key.data = sval;
+ data.size = sizeof(sval);
+ data.data = sval;
+
+ sprintf(sval, "%03x %d foo bar", 32, 3141592);
+ rc = dbi->put(dbi, txn, &key, &data, 0);
+ rc = txn->commit(txn, 0);
+ if (rc) {
+ fprintf(stderr, "txn->commit: (%d) %s\n", rc, db_strerror(rc));
+ goto leave;
+ }
+ rc = env->txn_begin(env, NULL, &txn, 0);
+ rc = dbi->cursor(dbi, txn, &cursor, 0);
+ key.flags = DB_DBT_USERMEM;
+ key.data = kval;
+ key.ulen = sizeof(kval);
+ data.flags = DB_DBT_USERMEM;
+ data.data = sval;
+ data.ulen = sizeof(sval);
+ while ((rc = cursor->c_get(cursor, &key, &data, DB_NEXT)) == 0) {
+ printf("key: %p %.*s, data: %p %.*s\n",
+ key.data, (int) key.size, (char *) key.data,
+ data.data, (int) data.size, (char *) data.data);
+ }
+ rc = cursor->c_close(cursor);
+ rc = txn->abort(txn);
+leave:
+ rc = dbi->close(dbi, 0);
+ rc = env->close(env, 0);
+ return rc;
+}
+++ /dev/null
-/* sample-mdb.c - MDB toy/sample
- *
- * Do a line-by-line comparison of this and sample-bdb.c
- */
-/*
- * Copyright 2012 Howard Chu, Symas Corp.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-#include <stdio.h>
-#include "lmdb.h"
-
-int main(int argc,char * argv[])
-{
- int rc;
- MDB_env *env;
- MDB_dbi dbi;
- MDB_val key, data;
- MDB_txn *txn;
- MDB_cursor *cursor;
- char sval[32];
-
- rc = mdb_env_create(&env);
- rc = mdb_env_open(env, "./testdb", 0, 0664);
- rc = mdb_txn_begin(env, NULL, 0, &txn);
- rc = mdb_open(txn, NULL, 0, &dbi);
-
- key.mv_size = sizeof(int);
- key.mv_data = sval;
- data.mv_size = sizeof(sval);
- data.mv_data = sval;
-
- sprintf(sval, "%03x %d foo bar", 32, 3141592);
- rc = mdb_put(txn, dbi, &key, &data, 0);
- rc = mdb_txn_commit(txn);
- if (rc) {
- fprintf(stderr, "mdb_txn_commit: (%d) %s\n", rc, mdb_strerror(rc));
- goto leave;
- }
- rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
- rc = mdb_cursor_open(txn, dbi, &cursor);
- while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
- printf("key: %p %.*s, data: %p %.*s\n",
- key.mv_data, (int) key.mv_size, (char *) key.mv_data,
- data.mv_data, (int) data.mv_size, (char *) data.mv_data);
- }
- mdb_cursor_close(cursor);
- mdb_txn_abort(txn);
-leave:
- mdb_close(env, dbi);
- mdb_env_close(env);
- return 0;
-}
--- /dev/null
+/* sample-mdb.txt - MDB toy/sample
+ *
+ * Do a line-by-line comparison of this and sample-bdb.txt
+ */
+/*
+ * Copyright 2012 Howard Chu, Symas Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+#include <stdio.h>
+#include "lmdb.h"
+
+int main(int argc,char * argv[])
+{
+ int rc;
+ MDB_env *env;
+ MDB_dbi dbi;
+ MDB_val key, data;
+ MDB_txn *txn;
+ MDB_cursor *cursor;
+ char sval[32];
+
+ /* Note: Most error checking omitted for simplicity */
+
+ rc = mdb_env_create(&env);
+ rc = mdb_env_open(env, "./testdb", 0, 0664);
+ rc = mdb_txn_begin(env, NULL, 0, &txn);
+ rc = mdb_open(txn, NULL, 0, &dbi);
+
+ key.mv_size = sizeof(int);
+ key.mv_data = sval;
+ data.mv_size = sizeof(sval);
+ data.mv_data = sval;
+
+ sprintf(sval, "%03x %d foo bar", 32, 3141592);
+ rc = mdb_put(txn, dbi, &key, &data, 0);
+ rc = mdb_txn_commit(txn);
+ if (rc) {
+ fprintf(stderr, "mdb_txn_commit: (%d) %s\n", rc, mdb_strerror(rc));
+ goto leave;
+ }
+ rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
+ rc = mdb_cursor_open(txn, dbi, &cursor);
+ while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
+ printf("key: %p %.*s, data: %p %.*s\n",
+ key.mv_data, (int) key.mv_size, (char *) key.mv_data,
+ data.mv_data, (int) data.mv_size, (char *) data.mv_data);
+ }
+ mdb_cursor_close(cursor);
+ mdb_txn_abort(txn);
+leave:
+ mdb_close(env, dbi);
+ mdb_env_close(env);
+ return 0;
+}