Repository: ofiwg/libfabric
Pull request #11004: prov/cxi: New conf opt for binding of json symbols
Author: login: SeanP-2023
Created: 2025-05-02T14:18:34Z | Merged: 2025-05-07T03:33:10Z

This opt was needed for static and dynamic binding of these symbols. 


Diff:
diff --git a/prov/cxi/configure.m4 b/prov/cxi/configure.m4
index 3bde7e2caef..0924fbd6f7e 100644
--- a/prov/cxi/configure.m4
+++ b/prov/cxi/configure.m4
@@ -42,18 +42,30 @@ AC_DEFUN([FI_CXI_CONFIGURE],[
 
 	# Support non-standard install path for json-c. This is needed by CXI provider.
 	AC_ARG_WITH([json-c],
-		[AS_HELP_STRING([--with-json-c=DIR], [Install directory for json-c])])
+		[AS_HELP_STRING([--with-json-c=DIR], [Install directory for json-c])],
+		[AC_DEFINE_UNQUOTED([FI_CXI_JSON_LIB_PATH], ["$with_json_c"], [Path to the json-c install root])])
 
     # Support for collectives dlopen/dlsym of curl libs.
-    coll_dlopen=0
+    coll_dlopen_curl=0
     AC_ARG_ENABLE([cxi-curl-dlopen],
     [AS_HELP_STRING([--enable-cxi-curl-dlopen], [Enable collectives dlopen of curl libraries @<:@default=no@:>@])],
     [
             AS_IF([test "$with_dlopen" = "no"], [AC_MSG_ERROR([dlopen not found.  libfabric requires libdl.])])
-            AS_IF([test "$enable_cxi_curl_dlopen" != "no"], [coll_dlopen=1])
+            AS_IF([test "$enable_cxi_curl_dlopen" != "no"], [coll_dlopen_curl=1])
     ])
     # define and set ENABLE_CXI_CURL_DLOPEN
-    AC_DEFINE_UNQUOTED([ENABLE_CXI_CURL_DLOPEN], [$coll_dlopen], [Enable collectives dlopen of curl libraries])
+    AC_DEFINE_UNQUOTED([ENABLE_CXI_CURL_DLOPEN], [$coll_dlopen_curl], [Enable collectives dlopen of curl libraries])
+
+    # Support for collectives dlopen/dlsym of json libs.
+    coll_dlopen_json=0
+    AC_ARG_ENABLE([cxi-json-dlopen],
+    [AS_HELP_STRING([--enable-cxi-json-dlopen], [Enable collectives dlopen of json libraries @<:@default=no@:>@])],
+    [
+            AS_IF([test "$with_dlopen" = "no"], [AC_MSG_ERROR([dlopen not found.  libfabric requires libdl.])])
+            AS_IF([test "$enable_cxi_json_dlopen" != "no"], [coll_dlopen_json=1])
+    ])
+    # define and set ENABLE_CXI_JSON_DLOPEN
+    AC_DEFINE_UNQUOTED([ENABLE_CXI_JSON_DLOPEN], [$coll_dlopen_json], [Enable collectives dlopen of json libraries])
 
 	AS_IF([test x"$enable_cxi" != x"no"],
 		[
@@ -108,8 +120,8 @@ AC_DEFUN([FI_CXI_CONFIGURE],[
 			cxi_CPPFLAGS="$cxi_CPPFLAGS $libcurl_CPPFLAGS"
 			cxi_LDFLAGS="$cxi_LDFLAGS $libcurl_LDFLAGS"
 			# check to see if we are dynamically linking the curl symbols
-			AS_IF([test "$coll_dlopen" = "0"], [cxi_LIBS="$cxi_LIBS $libcurl_LIBS"])
-			AC_MSG_NOTICE([After coll_dlopen check, cxi_LIBS = $cxi_LIBS])
+			AS_IF([test "$coll_dlopen_curl" = "0"], [cxi_LIBS="$cxi_LIBS $libcurl_LIBS"])
+			AC_MSG_NOTICE([After coll_dlopen_curl check, cxi_LIBS = $cxi_LIBS])
 			# Add on json if installed in non-default location.
 			if test "$with_json_c" != "" && test "$with_json_c" != "no"; then
 				FI_CHECK_PREFIX_DIR([$with_json_c], [json])
@@ -130,7 +142,9 @@ AC_DEFUN([FI_CXI_CONFIGURE],[
 
 			cxi_CPPFLAGS="$cxi_CPPFLAGS $libjson_CPPFLAGS"
 			cxi_LDFLAGS="$cxi_LDFLAGS $libjson_LDFLAGS"
-			cxi_LIBS="$cxi_LIBS $libjson_LIBS"
+			# check to see if we are dynamically linking the json symbols
+			AS_IF([test "$coll_dlopen_json" = "0"], [cxi_LIBS="$cxi_LIBS $libjson_LIBS"])
+			AC_MSG_NOTICE([After coll_dlopen_json check, cxi_LIBS = $cxi_LIBS])
 
 			# Need to explicitly link to libmath
 			cxi_LIBS="$cxi_LIBS -lm"
diff --git a/prov/cxi/include/cxip.h b/prov/cxi/include/cxip.h
index 6f90ef5c0f3..ac741dda5dd 100644
--- a/prov/cxi/include/cxip.h
+++ b/prov/cxi/include/cxip.h
@@ -3033,6 +3033,8 @@ int cxip_json_int64(const char *desc, struct json_object *jobj, int64_t *val);
 int cxip_json_double(const char *desc, struct json_object *jobj, double *val);
 int cxip_json_string(const char *desc, struct json_object *jobj,
 		     const char **val);
+struct json_object *cxip_json_tokener_parse(const char *str);
+void cxip_json_object_put(struct json_object *obj);
 
 /* Perform zero-buffer collectives */
 void cxip_tree_rowcol(int radix, int nodeidx, int *row, int *col, int *siz);
diff --git a/prov/cxi/src/cxip_coll.c b/prov/cxi/src/cxip_coll.c
index 5736eb61223..5523614a41c 100644
--- a/prov/cxi/src/cxip_coll.c
+++ b/prov/cxi/src/cxip_coll.c
@@ -3186,7 +3186,7 @@ static void _cxip_delete_mcast_cb(struct cxip_curl_handle *handle)
 	const char *errmsg = "";
 
 	/* note: allocates space for strings, free at end */
-	json_obj = json_tokener_parse(handle->response);
+	json_obj = cxip_json_tokener_parse(handle->response);
 	if (json_obj) {
 		if (cxip_json_string("message", json_obj, &errmsg))
 			errmsg = "";
@@ -3232,7 +3232,7 @@ static void _cxip_delete_mcast_cb(struct cxip_curl_handle *handle)
 		break;
 	}
 	/* free json memory */
-	json_object_put(json_obj);
+	cxip_json_object_put(json_obj);
 	free(curl_usrptr);
 }
 
@@ -3387,7 +3387,7 @@ static void _cxip_create_mcast_cb(struct cxip_curl_handle *handle)
 	int i, ret;
 
 	/* note: allocates space for strings, free at end */
-	json_obj = json_tokener_parse(handle->response);
+	json_obj = cxip_json_tokener_parse(handle->response);
 	if (json_obj) {
 		if (cxip_json_string("message", json_obj, &message))
 			message = "";
@@ -3520,7 +3520,7 @@ static void _cxip_create_mcast_cb(struct cxip_curl_handle *handle)
 	}
 	TRACE_JOIN("jstate->prov_errno = %d\n", jstate->prov_errno);
 	/* free json memory */
-	json_object_put(json_obj);
+	cxip_json_object_put(json_obj);
 	free(curl_usrptr);
 }
 
diff --git a/prov/cxi/src/cxip_curl.c b/prov/cxi/src/cxip_curl.c
index 3da17b778f8..4669c0eb488 100644
--- a/prov/cxi/src/cxip_curl.c
+++ b/prov/cxi/src/cxip_curl.c
@@ -16,8 +16,10 @@
 #include "cxip.h"
 
 static void *cxip_curlhandle;
+static void *cxip_jsonhandle;
 static CURLM *cxip_curlm;
 static int cxip_curl_count;
+static int cxip_json_dl_init(void);
 
 #define	TRACE_CURL(fmt, ...)	CXIP_COLL_TRACE(CXIP_TRC_COLL_CURL, fmt, \
 						##__VA_ARGS__)
@@ -307,6 +309,10 @@ int cxip_curl_init(void)
 	if (ret)
 		return ret;
 
+	ret = cxip_json_dl_init();
+	if (ret)
+		return ret;
+
 	if(!cxip_curlm) {
 		res = curldl_ops.dl_curl_global_init(CURL_GLOBAL_DEFAULT);
 		if (res == CURLE_OK) {
@@ -682,6 +688,137 @@ int cxip_curl_progress(struct cxip_curl_handle **handleptr)
 	return FI_SUCCESS;
 }
 
+struct jsondl_ops {
+        enum json_type (*dl_json_object_get_type)(const struct json_object *);
+        size_t (*dl_json_object_array_length)(const struct json_object *);
+        struct json_object * (*dl_json_object_array_get_idx)(const struct json_object *, size_t);
+        json_bool (*dl_json_object_object_get_ex)(const struct json_object *, const char *, struct json_object **);
+        json_bool (*dl_json_object_get_boolean)(const struct json_object *);
+        int32_t (*dl_json_object_get_int)(const struct json_object *);
+        int64_t (*dl_json_object_get_int64)(const struct json_object *);
+        double  (*dl_json_object_get_double)(const struct json_object *);
+        const char * (*dl_json_object_get_string)(struct json_object *);
+	struct json_object * (*dl_json_tokener_parse)(const char *);
+	void (*dl_json_object_put)(struct json_object *);
+};
+
+/* dynamic bind of symbols with dlopen()/dlsym() */
+#if ENABLE_CXI_JSON_DLOPEN
+
+#include <dlfcn.h>
+static struct jsondl_ops jsondl_ops;
+
+#else /* static bind of symbols */
+static struct jsondl_ops jsondl_ops = {
+        .dl_json_object_get_type = json_object_get_type,
+        .dl_json_object_array_length = json_object_array_length,
+        .dl_json_object_array_get_idx = json_object_array_get_idx,
+        .dl_json_object_object_get_ex = json_object_object_get_ex,
+        .dl_json_object_get_boolean = json_object_get_boolean,
+        .dl_json_object_get_int = json_object_get_int,
+        .dl_json_object_get_int64 = json_object_get_int64,
+        .dl_json_object_get_double = json_object_get_double,
+        .dl_json_object_get_string = json_object_get_string,
+	.dl_json_tokener_parse = json_tokener_parse,
+	.dl_json_object_put = json_object_put,
+};
+#endif
+
+static int cxip_json_dl_init(void)
+{
+#if ENABLE_CXI_JSON_DLOPEN
+	char *json_libpath = NULL;
+	char *lib_name = "libjson-c.so";
+
+	/* load successfully only once */
+	if (cxip_jsonhandle)
+		return FI_SUCCESS;
+/*
+ * Check for non standard search path
+ */
+#ifdef FI_CXI_JSON_LIB_PATH
+        json_libpath = strdup(FI_CXI_JSON_LIB_PATH);
+        TRACE_CURL("FI_CXI_JSON_LIB_PATH set to %s\n", json_libpath);
+#else/* standard lookup of libjson-c.so */
+        json_libpath = strdup(lib_name);
+        TRACE_CURL("libjson-c path set to %s\n", json_libpath);
+#endif
+	cxip_jsonhandle = dlopen(lib_name, RTLD_NOW);
+	if (!cxip_jsonhandle) {
+		TRACE_CURL("Unable to dlopen libjson - lib_name = %s\n", lib_name);
+		free(json_libpath);
+		return -FI_ENOSYS;
+	}
+	jsondl_ops.dl_json_object_get_type = dlsym(cxip_jsonhandle, "json_object_get_type");
+	if (!jsondl_ops.dl_json_object_get_type) {
+		TRACE_CURL("Failed to find json_object_get_type\n");
+		goto err;
+	}
+	jsondl_ops.dl_json_object_array_length = dlsym(cxip_jsonhandle, "json_object_array_length");
+	if (!jsondl_ops.dl_json_object_array_length) {
+		TRACE_CURL("Failed to find json_object_array_length\n");
+		goto err;
+	}
+	jsondl_ops.dl_json_object_array_get_idx = dlsym(cxip_jsonhandle, "json_object_array_get_idx");
+	if (!jsondl_ops.dl_json_object_array_get_idx) {
+		TRACE_CURL("Failed to find json_object_array_get_idx\n");
+		goto err;
+	}
+	jsondl_ops.dl_json_object_object_get_ex = dlsym(cxip_jsonhandle, "json_object_object_get_ex");
+	if (!jsondl_ops.dl_json_object_object_get_ex) {
+		TRACE_CURL("Failed to find json_object_object_get_ex\n");
+		goto err;
+	}
+	jsondl_ops.dl_json_object_get_boolean = dlsym(cxip_jsonhandle, "json_object_get_boolean");
+	if (!jsondl_ops.dl_json_object_get_boolean) {
+		TRACE_CURL("Failed to find json_object_get_boolean\n");
+		goto err;
+	}
+	jsondl_ops.dl_json_object_get_int = dlsym(cxip_jsonhandle, "json_object_get_int");
+	if (!jsondl_ops.dl_json_object_get_int) {
+		TRACE_CURL("Failed to find json_object_get_int\n");
+		goto err;
+	}
+	jsondl_ops.dl_json_object_get_int64 = dlsym(cxip_jsonhandle, "json_object_get_int64");
+	if (!jsondl_ops.dl_json_object_get_int64) {
+		TRACE_CURL("Failed to find json_object_get_int64\n");
+		goto err;
+	}
+	jsondl_ops.dl_json_object_get_double = dlsym(cxip_jsonhandle, "json_object_get_double");
+	if (!jsondl_ops.dl_json_object_get_double) {
+		TRACE_CURL("Failed to find json_object_get_double\n");
+		goto err;
+	}
+	jsondl_ops.dl_json_object_get_string = dlsym(cxip_jsonhandle, "json_object_get_string");
+	if (!jsondl_ops.dl_json_object_get_string) {
+		TRACE_CURL("Failed to find json_object_get_string\n");
+		goto err;
+	}
+	jsondl_ops.dl_json_tokener_parse = dlsym(cxip_jsonhandle, "json_tokener_parse");
+	if (!jsondl_ops.dl_json_tokener_parse) {
+		TRACE_CURL("Failed to find json_tokener_parse\n");
+		goto err;
+	}
+	jsondl_ops.dl_json_object_put = dlsym(cxip_jsonhandle, "json_object_put");
+	if (!jsondl_ops.dl_json_object_put) {
+		TRACE_CURL("Failed to find json_object_put\n");
+		goto err;
+	}
+
+	TRACE_CURL("JSON DLOPEN SUCCESS\n");
+	free(json_libpath);
+	return FI_SUCCESS;
+err:
+	TRACE_CURL("JSON DLOPEN FAILURE\n");
+	free(json_libpath);
+	dlclose(cxip_jsonhandle);
+	return -FI_ENODATA;
+#else
+	TRACE_CURL("JSON DLOPEN UNAVAILABLE\n");
+	return FI_SUCCESS;
+#endif
+}
+
 /**
  * @brief Simplified search for JSON objects.
  *
@@ -737,7 +874,7 @@ enum json_type cxip_json_extract(const char *desc, struct json_object *jobj,
 
 	beg = desc;
 	jo = jobj;
-	jt = json_object_get_type(jo);
+	jt = jsondl_ops.dl_json_object_get_type(jo);
 	while (*beg) {
 		if (*beg == '[') {
 			/* expect "[<integer>]" */
@@ -754,12 +891,12 @@ enum json_type cxip_json_extract(const char *desc, struct json_object *jobj,
 			if (*(beg++) != ']')
 				return json_type_null;
 			/* check index validity */
-			len = json_object_array_length(jo);
+			len = jsondl_ops.dl_json_object_array_length(jo);
 			if (idx >= len)
 				return json_type_null;
 			/* get the indexed object and continue */
-			jo = json_object_array_get_idx(jo, idx);
-			jt = json_object_get_type(jo);
+			jo = jsondl_ops.dl_json_object_array_get_idx(jo, idx);
+			jt = jsondl_ops.dl_json_object_get_type(jo);
 			continue;
 		}
 		if (beg == desc || *beg == '.') {
@@ -777,9 +914,9 @@ enum json_type cxip_json_extract(const char *desc, struct json_object *jobj,
 				*p++ = *beg++;
 			*p = 0;
 			/* extract the associated value */
-			if (!json_object_object_get_ex(jo, key, &jo))
+			if (!jsondl_ops.dl_json_object_object_get_ex(jo, key, &jo))
 				return json_type_null;
-			jt = json_object_get_type(jo);
+			jt = jsondl_ops.dl_json_object_get_type(jo);
 			continue;
 		}
 	}
@@ -802,7 +939,7 @@ int cxip_json_bool(const char *desc, struct json_object *jobj, bool *val)
 	struct json_object *jval;
 	if (json_type_boolean != cxip_json_extract(desc, jobj, &jval))
 		return -EINVAL;
-	*val = json_object_get_boolean(jval);
+	*val = jsondl_ops.dl_json_object_get_boolean(jval);
 	return 0;
 }
 
@@ -811,7 +948,7 @@ int cxip_json_int(const char *desc, struct json_object *jobj, int *val)
 	struct json_object *jval;
 	if (json_type_int != cxip_json_extract(desc, jobj, &jval))
 		return -EINVAL;
-	*val = json_object_get_int(jval);
+	*val = jsondl_ops.dl_json_object_get_int(jval);
 	return 0;
 }
 
@@ -820,7 +957,7 @@ int cxip_json_int64(const char *desc, struct json_object *jobj, int64_t *val)
 	struct json_object *jval;
 	if (json_type_int != cxip_json_extract(desc, jobj, &jval))
 		return -EINVAL;
-	*val = json_object_get_int64(jval);
+	*val = jsondl_ops.dl_json_object_get_int64(jval);
 	return 0;
 }
 
@@ -829,7 +966,7 @@ int cxip_json_double(const char *desc, struct json_object *jobj, double *val)
 	struct json_object *jval;
 	if (json_type_double != cxip_json_extract(desc, jobj, &jval))
 		return -EINVAL;
-	*val = json_object_get_double(jval);
+	*val = jsondl_ops.dl_json_object_get_double(jval);
 	return 0;
 }
 
@@ -839,6 +976,16 @@ int cxip_json_string(const char *desc, struct json_object *jobj,
 	struct json_object *jval;
 	if (json_type_string != cxip_json_extract(desc, jobj, &jval))
 		return -EINVAL;
-	*val = json_object_get_string(jval);
+	*val = jsondl_ops.dl_json_object_get_string(jval);
 	return 0;
 }
+
+struct json_object *cxip_json_tokener_parse(const char *str)
+{
+	return jsondl_ops.dl_json_tokener_parse(str);
+}
+
+void cxip_json_object_put(struct json_object *obj)
+{
+	jsondl_ops.dl_json_object_put(obj);
+}
diff --git a/prov/cxi/test/curl.c b/prov/cxi/test/curl.c
index 143a8b1fe92..32c3d78da41 100644
--- a/prov/cxi/test/curl.c
+++ b/prov/cxi/test/curl.c
@@ -101,7 +101,7 @@ int auto_test_cxip_json(void)
 	single_to_double_quote(json2);
 
 	/* Test parsing of json1 */
-	if (!(json_obj = json_tokener_parse(json1)))
+	if (!(json_obj = cxip_json_tokener_parse(json1)))
 		failtest(return 1, "json1 could not be parsed\n");
 
 	key = "string";
@@ -187,10 +187,10 @@ int auto_test_cxip_json(void)
 		if (int_val != i)
 			failtest(return 1, "'%s' returned %d\n", key, int_val);
 	}
-	json_object_put(json_obj);
+	cxip_json_object_put(json_obj);
 
 	/* Test parsing of json2 */
-	if (!(json_obj = json_tokener_parse(json2)))
+	if (!(json_obj = cxip_json_tokener_parse(json2)))
 		failtest(return 1, "json2 could not be parsed\n");
 	for (i = 0; i < 4; i++) {
 		char key[256];
@@ -200,7 +200,7 @@ int auto_test_cxip_json(void)
 		if (int_val != i)
 			failtest(return 1, "'%s' returned %d\n", key, int_val);
 	}
-	json_object_put(json_obj);
+	cxip_json_object_put(json_obj);
 
 	if (verbose)
 		printf("PASSED JSON tests\n");
@@ -328,7 +328,7 @@ int auto_test_cxip_curl(void)
 			 * }
 			 */
 			const char *str;
-			json_obj = json_tokener_parse(handle->response);
+			json_obj = cxip_json_tokener_parse(handle->response);
 			if (! json_obj) {
 				fprintf(stderr, "%s: JSON unparseable\n",
 					opname);
@@ -362,7 +362,7 @@ int auto_test_cxip_curl(void)
 			if (seqid != nextseqid)
 				reordered = true;
 free_json:
-			json_object_put(json_obj);
+			cxip_json_object_put(json_obj);
 free_handle:
 			cxip_curl_free(handle);
 			nextseqid++;


Reviews:
user: login: j-xiong
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-02T22:13:40Z
user: login: SeanP-2023
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-03T19:02:20Z
user: login: SeanP-2023
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-03T19:04:01Z
user: login: SeanP-2023
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-03T19:06:28Z
user: login: swelch
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-05T13:46:01Z

Review comments:
diff_hunk: @@ -839,6 +976,16 @@ int cxip_json_string(const char *desc, struct json_object *jobj,
 	struct json_object *jval;
 	if (json_type_string != cxip_json_extract(desc, jobj, &jval))
 		return -EINVAL;
-	*val = json_object_get_string(jval);
+	*val = jsondl_ops.dl_json_object_get_string(jval);
 	return 0;
 }
+
+struct json_object *cxip_json_tokener_parse(const char *str)
+{
+	return(jsondl_ops.dl_json_tokener_parse(str));
path: prov/cxi/src/cxip_curl.c
user: login: j-xiong
body: `return` is not a function call. Leave a space after `return` and remove the outmost parentheses.
created_at: 2025-05-02T22:05:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -682,6 +688,137 @@ int cxip_curl_progress(struct cxip_curl_handle **handleptr)
 	return FI_SUCCESS;
 }
 
+struct jsondl_ops {
+        enum json_type (*dl_json_object_get_type) (const struct json_object *);
+        size_t (*dl_json_object_array_length) (const struct json_object *);
+        struct json_object * (*dl_json_object_array_get_idx) (const struct json_object *, size_t);
+        json_bool (*dl_json_object_object_get_ex) (const struct json_object *, const char *, struct json_object **);
+        json_bool (*dl_json_object_get_boolean) (const struct json_object *);
+        int32_t (*dl_json_object_get_int) (const struct json_object *);
+        int64_t (*dl_json_object_get_int64) (const struct json_object *);
+        double  (*dl_json_object_get_double) (const struct json_object *);
+        const char * (*dl_json_object_get_string) (struct json_object *);
+	struct json_object * (*dl_json_tokener_parse) (const char *);
+	void (*dl_json_object_put) (struct json_object *);
+};
+
+/* dynamic bind of symbols with dlopen()/dlsym() */
+#if ENABLE_CXI_JSON_DLOPEN
+
+#include <dlfcn.h>
+static struct jsondl_ops jsondl_ops;
+
+#else /* static bind of symbols */
+static struct jsondl_ops jsondl_ops = {
+        .dl_json_object_get_type = json_object_get_type,
+        .dl_json_object_array_length = json_object_array_length,
+        .dl_json_object_array_get_idx = json_object_array_get_idx,
+        .dl_json_object_object_get_ex = json_object_object_get_ex,
+        .dl_json_object_get_boolean = json_object_get_boolean,
+        .dl_json_object_get_int = json_object_get_int,
+        .dl_json_object_get_int64 = json_object_get_int64,
+        .dl_json_object_get_double = json_object_get_double,
+        .dl_json_object_get_string = json_object_get_string,
+	.dl_json_tokener_parse = json_tokener_parse,
+	.dl_json_object_put = json_object_put,
+};
+#endif
+
+static int cxip_json_dl_init(void)
+{
+#if ENABLE_CXI_JSON_DLOPEN
+	char *json_libpath = NULL;
+	char *lib_name = "libjson-c.so";
+
+	/* load successfully only once */
+	if (cxip_jsonhandle)
+		return 0;
path: prov/cxi/src/cxip_curl.c
user: login: j-xiong
body: use `FI_SUCCESS` here to be consistent with the rest of the function. 
created_at: 2025-05-02T22:07:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -682,6 +688,137 @@ int cxip_curl_progress(struct cxip_curl_handle **handleptr)
 	return FI_SUCCESS;
 }
 
+struct jsondl_ops {
+        enum json_type (*dl_json_object_get_type) (const struct json_object *);
+        size_t (*dl_json_object_array_length) (const struct json_object *);
+        struct json_object * (*dl_json_object_array_get_idx) (const struct json_object *, size_t);
+        json_bool (*dl_json_object_object_get_ex) (const struct json_object *, const char *, struct json_object **);
+        json_bool (*dl_json_object_get_boolean) (const struct json_object *);
+        int32_t (*dl_json_object_get_int) (const struct json_object *);
+        int64_t (*dl_json_object_get_int64) (const struct json_object *);
+        double  (*dl_json_object_get_double) (const struct json_object *);
+        const char * (*dl_json_object_get_string) (struct json_object *);
+	struct json_object * (*dl_json_tokener_parse) (const char *);
+	void (*dl_json_object_put) (struct json_object *);
path: prov/cxi/src/cxip_curl.c
user: login: j-xiong
body: Remove the space between `)` and `(`.
created_at: 2025-05-02T22:13:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -839,6 +976,16 @@ int cxip_json_string(const char *desc, struct json_object *jobj,
 	struct json_object *jval;
 	if (json_type_string != cxip_json_extract(desc, jobj, &jval))
 		return -EINVAL;
-	*val = json_object_get_string(jval);
+	*val = jsondl_ops.dl_json_object_get_string(jval);
 	return 0;
 }
+
+struct json_object *cxip_json_tokener_parse(const char *str)
+{
+	return(jsondl_ops.dl_json_tokener_parse(str));
path: prov/cxi/src/cxip_curl.c
user: login: SeanP-2023
body: old habits are hard to break! Done.
created_at: 2025-05-03T19:02:20Z
author_association: NONE
diff_hunk: @@ -682,6 +688,137 @@ int cxip_curl_progress(struct cxip_curl_handle **handleptr)
 	return FI_SUCCESS;
 }
 
+struct jsondl_ops {
+        enum json_type (*dl_json_object_get_type) (const struct json_object *);
+        size_t (*dl_json_object_array_length) (const struct json_object *);
+        struct json_object * (*dl_json_object_array_get_idx) (const struct json_object *, size_t);
+        json_bool (*dl_json_object_object_get_ex) (const struct json_object *, const char *, struct json_object **);
+        json_bool (*dl_json_object_get_boolean) (const struct json_object *);
+        int32_t (*dl_json_object_get_int) (const struct json_object *);
+        int64_t (*dl_json_object_get_int64) (const struct json_object *);
+        double  (*dl_json_object_get_double) (const struct json_object *);
+        const char * (*dl_json_object_get_string) (struct json_object *);
+	struct json_object * (*dl_json_tokener_parse) (const char *);
+	void (*dl_json_object_put) (struct json_object *);
+};
+
+/* dynamic bind of symbols with dlopen()/dlsym() */
+#if ENABLE_CXI_JSON_DLOPEN
+
+#include <dlfcn.h>
+static struct jsondl_ops jsondl_ops;
+
+#else /* static bind of symbols */
+static struct jsondl_ops jsondl_ops = {
+        .dl_json_object_get_type = json_object_get_type,
+        .dl_json_object_array_length = json_object_array_length,
+        .dl_json_object_array_get_idx = json_object_array_get_idx,
+        .dl_json_object_object_get_ex = json_object_object_get_ex,
+        .dl_json_object_get_boolean = json_object_get_boolean,
+        .dl_json_object_get_int = json_object_get_int,
+        .dl_json_object_get_int64 = json_object_get_int64,
+        .dl_json_object_get_double = json_object_get_double,
+        .dl_json_object_get_string = json_object_get_string,
+	.dl_json_tokener_parse = json_tokener_parse,
+	.dl_json_object_put = json_object_put,
+};
+#endif
+
+static int cxip_json_dl_init(void)
+{
+#if ENABLE_CXI_JSON_DLOPEN
+	char *json_libpath = NULL;
+	char *lib_name = "libjson-c.so";
+
+	/* load successfully only once */
+	if (cxip_jsonhandle)
+		return 0;
path: prov/cxi/src/cxip_curl.c
user: login: SeanP-2023
body: Done, makes sense...
created_at: 2025-05-03T19:04:00Z
author_association: NONE
diff_hunk: @@ -682,6 +688,137 @@ int cxip_curl_progress(struct cxip_curl_handle **handleptr)
 	return FI_SUCCESS;
 }
 
+struct jsondl_ops {
+        enum json_type (*dl_json_object_get_type) (const struct json_object *);
+        size_t (*dl_json_object_array_length) (const struct json_object *);
+        struct json_object * (*dl_json_object_array_get_idx) (const struct json_object *, size_t);
+        json_bool (*dl_json_object_object_get_ex) (const struct json_object *, const char *, struct json_object **);
+        json_bool (*dl_json_object_get_boolean) (const struct json_object *);
+        int32_t (*dl_json_object_get_int) (const struct json_object *);
+        int64_t (*dl_json_object_get_int64) (const struct json_object *);
+        double  (*dl_json_object_get_double) (const struct json_object *);
+        const char * (*dl_json_object_get_string) (struct json_object *);
+	struct json_object * (*dl_json_tokener_parse) (const char *);
+	void (*dl_json_object_put) (struct json_object *);
path: prov/cxi/src/cxip_curl.c
user: login: SeanP-2023
body: done
created_at: 2025-05-03T19:06:28Z
author_association: NONE

PR comments:
user: login: swelch
created_at: 2025-05-05T22:41:51Z
body: @wzamazon - I assume the AWS failure is unrelated, you ok with us merging?
author_association: CONTRIBUTOR
user: login: j-xiong
created_at: 2025-05-06T06:30:20Z
body: bot:aws:retest
author_association: CONTRIBUTOR
user: login: SeanP-2023
created_at: 2025-05-06T12:25:01Z
body: is that command supposed to kick off another retest?
author_association: NONE