[Date Prev][Date Next] [Chronological] [Thread] [Top]

(ITS#8276) [PATCH 2/2] Add an application context pointer into user-defined key compare and dupsort functions



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;
 }