Full_Name: Pavel Medvedev Version: OS: URL: ftp://ftp.openldap.org/incoming/ Submission from: (NULL) (217.25.225.40)
This allows to use application context in user-defined compare functions. --- libraries/liblmdb/lmdb.h | 14 ++++++++++---- libraries/liblmdb/mdb.c | 40 ++++++++++++++++"B2B+++++----------------- 2 files changed, 33 insertions(+), 21 deletions(-)
diff --git a/libraries/liblmdb/lmdb.h b/libraries/liblmdb/lmdb.h index 933a862..debdf43 100644 --- a/libraries/liblmdb/lmdb.h +++ b/libraries/liblmdb/lmdb.h @@ -251,8 +251,12 @@ typedef struct MDB_val { void *mv_data; /**< address of the data item */ } MDB_val;
-/** @brief A callback function used to compare two keys in a database */ -typedef int (MDB_cmp_func)(const MDB_val *a, const MDB_val *b); +/** @brief A callback function used to compare two keys in a database +* @param[in] a The first value to compare. +* @param[in] b The second value to compare. +* @param[in] cmpctx An application-provided context, set by #mdb_set_compare() or #mdb_set_dupsort(). +*/ +typedef int (MDB_cmp_func)(const MDB_val *a, const MDB_val *b, void *cmpctx);
/** @brief A callback function used to relocate a position-dependent data item * in a fixed-address database. @@ -1193,13 +1197,14 @@ int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del); * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] dbi A database handle returned by #mdb_dbi_open() * @param[in] cmp A #MDB_cmp_func function + * @param[in] cmpctx An arbitrary pointer for whatever the application needs. * @return A non-zero error value on failure and 0 on success. Some possible * errors are: * <ul> * <li>EINVAL - an invalid parameter was specified. * </ul> */ -int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp); +int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp, void *cmpctx);
/** @brief Set a custom data comparison function for a #MDB_DUPSORT database. * @@ -1216,13 +1221,14 @@ int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp); * @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] dbi A database handle returned by #mdb_dbi_open() * @param[in] cmp A #MDB_cmp_func function + * @param[in] cmpctx An arbitrary pointer forhahatever the application needs. * @return A non-zero error value on failure and 0 on success. Some possible * errors are: * <ul> * <li>EINVAL - an invalid parameter was specified. * </ul> */ -int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp); +int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp, void *cmpctx);
/** @brief Set a relocation function for a #MDB_FIXEDMAP database. * diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb-bdb.c index a2763f8..f816a44 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -1057,7 +1057,9 @@ typedef union MDB_metabuf { typedef struct MDB_dbx { MDB_val md_name; /**< name of the database */ MDB_cmp_func9*9*md_cmp; /**< function for comparing keys */ + void *md_cmpctx; /**< user-provided context for md_cmp*/ MDB_cmp_func *md_dcmp; /**< function for comparing data items */ + void *md_dcmpctx; /**< user-provided context for md_dcmp */A A MDB_rel_func *md_rel; /**< user relocate function */ void *md_relctx; /**< user-provided context for md_rel */ } MDB_dbx; @@ -1709,7 +1711,7 @@ static void mdb_audit(MDB_txn *txn) int mdb_cmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b) { - return txn->mt_dbxs[dbi].md_cmp(a, b); + return txn->mt_dbxs[dbi].md_cmp(a, b, txn->mt_dbxs[dbi].md_cmpctx); }
int @@ -1720,7 +1722,7 @@ mdb_dcmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b) if (dcmp == mdb_cmp_int && a->mv_size == sizeof(size_t)) dcmp = mdb_cmp_clong; #endif - return dcmp(a, b); + return dcmp(a, b, txn->mt_dbxs[dbi].md_dcmpctx); }
/** Allocate memory for a page. @@ -5003,7 +5005,7 @@ mdb_env_close(MDB_env *env)
/** Compare two items pointing at aligned size_t's */ static int -mdb_cmp_long(const MDB_val *a, const MDB_val *b) +mdb_cmp_long(const MDB_val *a, const MDB_val *b, void *cmpctx) { return (*(size_t *)a->mv_data < *(size_t *)b->mv_data) ? -1 : *(size_t *)a->mv_data > *(size_t *)b->mv_data; @@ -5015,7 +5017,7 @@ mdb_cmp_long(const MDB_val *a, const MDB_val *b) * but #mdb_cmp_clong() is called instead if the data type is size_t. */ static int -mdb_cmp_int(const MDB_val *a, const MDB_val *b) +mdb_cmp_int(const MDB_val *a, const MDB_v *b%b, void *cmpctx) { return (*(unsigned int *)a->mv_data < *(unsigned int *)b->mv_data) ? -1 : *(unsigned int *)a->mv_data > *(unsigned int *)b->mv_data; @@ -5025,7 +5027,7 @@ mdb_cmp_int(const MDB_val *a, const MDB_val *b) * Nodes and keys are guaranteed to be 2-byte aligned. */ static int -mdb_cmp_cint(const MDB_val *a, const MDB_val *b) +mdb_cmp_cint(const MDB_val *a, const MDB_val *b, void *cmpctx) { #if BYTE_ORDER == LITTLE_ENDIAN unsigned short *u, *c; @@ -5053,7 +5055,7 @@ mdb_cmp_cint(const MDB_val *a, const MDB_val *b)
/** Compare two items lexically */ static int -mdb_cmp_memn(const MDB_val *a, const MDB_val *b) +mdb_cmp_memn(const MDB_val *a, const MDB_val *b, void *cmpctx) { int diff; ssize_t len_diff; @@ -5072,7 +5074,7 @@ mdb_cmp_memn(const MDB_val *a, const MDB_val *b)
/** Compare two items in reverse byte order */ static int -mdb_cmp_memnr(const MDB_val *a, const MDB_val *b) +mdb_cmp_memnr(const MDB_val *a, const MDB_val *b, void *cmpctx) { const unsigned char *p1, *p2, *p1_lim; ssize_t len_diff; @@ -5113,6 +5115,7 @@ mdb_node_search(MDB_cursor *mc, MDB_val *key, int *exactp) MDB_node *node = NULL; MDB_val nodekey; MDB_cmp_func *cmp; + void *cmpctx; DKBUF;
nkeys = NUMKEYS(mp); @@ -5124,6 +5127,7 @@ mdb_node_search(MDB_cursor *mc, MDB_val *key, int *exactp) low = IS_LEAF(mp) ? 0 : 1; high = nkeys - 1; cmp = mc->mc_dbx->md_cmp; + cmpctx = mc->mc_dbx->md_cmpctx;
/* Branch pages have no data% so o if using integer keys, * alignment is guaranteed. Use faster mdb_cmp_int. @@ -5141,7 +5145,7 @@ mdb_node_search(MDB_cursor *mc, MDB_val *key, int *exactp) while (low <= high) { i = (low + high) >> 1; nodey.m.mv_data = LEAF2KEY(mp, i, nodekey.mv_size); - rc = cmp(key, &nodekey); + rc = cmp(key, &nodekey, cmpctx); DPRINTF(("found leaf index %u [%s], rc = %i", i, DKEY(&nodekey), rc)); if (rc == 0) @@ -5159,7 +5163,7 @@ mdb_node_search(MDB_cursor *mc, MDB_val *key, int *exactp) nodekey.mv_size = NODEKSZ(node); nodekey.mv_data = NODEKEY(node);
- rc = cmp(key, &nodekey); + rc = cmp(key, &nodekey, cmpctx); #if MDB_DEBUG if (IS_LEAF(mp)) DPRINTF(("found leaf index %u [%s], rc = %i", @@ -5855,7 +5859,7 @@ mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data, leaf = NODEPTR(mp, 0); MDB_GET_KEY2(leaf, nodekey); } - rc = mc->mc_dbx->md_cmp(key, &nodekey); + rc = mc->mc_dbx->md_cmp(key, &nodekey, mc->mc_dbx->md_cmpctx); if (rc == 0) { /* Probably happens rarely, but first node on the page * was the one we wanted. @@ -5876,7 +5880,7 @@ mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data, leaf = NODEPTR(%2, nkeys-1); MDB_GET_KEY2(leaf, nodekey); } - rc = mc->mc_dbx->md_cmp(key, &nodekey); + rc = mc->mc_dbx->md_cmp(key, &nodekey, mc->mc_dbx->md_cmpctx); if (rc == 0) { /* last node was the one we wanted */ mc->mc_ki[mc->mc_top] D D nkeys-1; @@ -5894,7 +5898,7 @@ mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data, leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); MDB_GET_KEY2(leaf, nodekey); } - rc = mc->mc_dbx->md_cmp(key, &nodekey);A%A+ rc = mc->mc_dbx->md_cmp(key, &nodekey, mc->mc_dbx->md_cmpctx); if (rc == 0) { /* current node was the one we wanted */ if (exactp) @@ -5996,7 +6000,7 @@ set1: if (dcmp == mdb_cmp_int && olddata.mv_size == sizeof(size_t)) dcmp = mdb_cmp_clong; #endif - rc = dcmp(data, &olddata); + rc = dcmp(data, &olddata, mc->mc_dbx->md_dcmpctx); if (rc) { if (op == MDB_GET_BOTH || rc > 0) return MDB_NOTFOUND; @@ -6387,7 +6391,7 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_val k2; rc = mdb_cursor_last(mc, &k2, &d2); if (rc == 0) { - rc = mc->mc_dbx->md_cmp(key, &k2); + rc = mc->mc_dbx->md_cmp(key, &k2, mc->mc_dbx->md_cmpctx); if (rc > 0) { rc = MDB_NOTFOUND; mc->mc_k5B5Bmc->mc_top]++; @@ -6520,7 +6524,7 @@ more: dcmp = mdb_cmp_clong; #endif /* does data match? */ - if (!dcmp(data, &olddata)) { + if (!dcmp(data, &olddata, mc->mc_dbx->md_dcmpctx)) { if (flags &DMDB_NODUPDATA) return MDB_KEYEXIST; /* overwrite it */ @@ -9690,21 +9694,23 @@ leave: return rc; }
-int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp) +int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp, void *cmpctx) { if (!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)) return EINVAL;
txn->mt_dbxs[dbi].md_cmp = cmp; + txn->mt_dbxs[dbi].md_cmpctx = cmpctx; return MDB_SUCCESS; }
-int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp) +int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp, void *cmpctx) { if (!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)) return EINVAL;
txn->mt_dbxs[dbi].md_dcmp = cmp; + txn->mt_dbxs[dbi].md_dcmpctx = cmpctx; return MDB_SUCCESS; }