Skip to content
Permalink
Browse files

Merge pull request #835 from garlick/json_c

Pull in json-c, allowing internals to link against alternate json libraries.
Add enhanced flux_rpc functions using libjansson json_pack/unpack functions
  • Loading branch information...
grondo committed Oct 11, 2016
2 parents 7eb19d0 + ded4a18 commit 286b6e7c4d94ca35d4eec9e3c828f2aa91a63e58
Showing with 6,510 additions and 657 deletions.
  1. +1 −0 .travis.yml
  2. +2 −1 Makefile.am
  3. +114 −0 config/ax_compile_check_sizeof.m4
  4. +32 −3 configure.ac
  5. +10 −4 doc/man3/Makefile.am
  6. +22 −6 doc/man3/flux_rpc.adoc
  7. +23 −17 doc/man3/flux_rpc_multi.adoc
  8. +1 −1 doc/man3/trpc.c
  9. +1 −1 doc/man3/trpc_then.c
  10. +3 −1 doc/man3/trpc_then_multi.c
  11. +5 −0 doc/test/spell.en.pws
  12. +0 −1 etc/Makefile.am
  13. +0 −14 etc/Makefile.inc.in
  14. +2 −2 src/bindings/lua/Makefile.am
  15. +1 −1 src/bindings/lua/json-lua.c
  16. +1 −1 src/bindings/lua/json-lua.h
  17. +1 −1 src/bindings/lua/zmsg-lua.h
  18. +1 −2 src/bindings/python/flux/Makefile.am
  19. +1 −1 src/bindings/python/flux/rpc.py
  20. +0 −8 src/bindings/python/make_binding.py
  21. +1 −1 src/broker/Makefile.am
  22. +2 −2 src/broker/content-cache.c
  23. +1 −2 src/broker/modservice.c
  24. +0 −1 src/broker/module.c
  25. +2 −2 src/cmd/Makefile.am
  26. +1 −1 src/cmd/builtin/attr.c
  27. +5 −5 src/cmd/builtin/content.c
  28. +3 −3 src/cmd/builtin/heaptrace.c
  29. +5 −4 src/cmd/builtin/hwloc.c
  30. +4 −4 src/cmd/flux-comms-stats.c
  31. +1 −1 src/cmd/flux-event.c
  32. +0 −1 src/cmd/flux-jstat.c
  33. +0 −1 src/cmd/flux-kvs.c
  34. +11 −10 src/cmd/flux-module.c
  35. +3 −5 src/cmd/flux-ping.c
  36. +3 −2 src/common/Makefile.am
  37. +1 −1 src/common/libcompat/Makefile.am
  38. +1 −1 src/common/libcompat/request.h
  39. +1 −1 src/common/libcompat/rpc.c
  40. +1 −1 src/common/libcompat/rpc.h
  41. +3 −2 src/common/libflux/Makefile.am
  42. +29 −39 src/common/libflux/attr.c
  43. +0 −3 src/common/libflux/event.c
  44. +7 −23 src/common/libflux/flog.c
  45. +20 −10 src/common/libflux/heartbeat.c
  46. +106 −71 src/common/libflux/module.c
  47. +2 −5 src/common/libflux/panic.c
  48. +1 −2 src/common/libflux/reduce.c
  49. +3 −7 src/common/libflux/reparent.c
  50. +0 −4 src/common/libflux/request.c
  51. +149 −70 src/common/libflux/rpc.c
  52. +27 −11 src/common/libflux/rpc.h
  53. +0 −1 src/common/libflux/security.c
  54. +5 −0 src/common/libjson-c/AUTHORS
  55. +42 −0 src/common/libjson-c/COPYING
  56. +53 −0 src/common/libjson-c/Makefile.am
  57. +101 −0 src/common/libjson-c/arraylist.c
  58. +56 −0 src/common/libjson-c/arraylist.h
  59. +28 −0 src/common/libjson-c/bits.h
  60. +83 −0 src/common/libjson-c/debug.c
  61. +71 −0 src/common/libjson-c/debug.h
  62. +35 −0 src/common/libjson-c/json.h
  63. +20 −0 src/common/libjson-c/json_c_version.c
  64. +22 −0 src/common/libjson-c/json_c_version.h
  65. +28 −0 src/common/libjson-c/json_inttypes.h
  66. +855 −0 src/common/libjson-c/json_object.c
  67. +612 −0 src/common/libjson-c/json_object.h
  68. +168 −0 src/common/libjson-c/json_object_iterator.c
  69. +239 −0 src/common/libjson-c/json_object_iterator.h
  70. +47 −0 src/common/libjson-c/json_object_private.h
  71. +887 −0 src/common/libjson-c/json_tokener.c
  72. +208 −0 src/common/libjson-c/json_tokener.h
  73. +300 −0 src/common/libjson-c/json_util.c
  74. +41 −0 src/common/libjson-c/json_util.h
  75. +602 −0 src/common/libjson-c/linkhash.c
  76. +292 −0 src/common/libjson-c/linkhash.h
  77. +113 −0 src/common/libjson-c/namespace.h
  78. +192 −0 src/common/libjson-c/printbuf.c
  79. +77 −0 src/common/libjson-c/printbuf.h
  80. +237 −0 src/common/libjson-c/random_seed.c
  81. +25 −0 src/common/libjson-c/random_seed.h
  82. +300 −0 src/common/libjson-c/test/json_c.c
  83. +3 −2 src/common/libpmi/Makefile.am
  84. +1 −1 src/common/libsubprocess/Makefile.am
  85. +0 −1 src/common/libsubprocess/subprocess.h
  86. +1 −1 src/common/libsubprocess/test/loop.c
  87. +1 −1 src/common/libsubprocess/test/socketpair.c
  88. +1 −1 src/common/libsubprocess/test/subprocess.c
  89. +1 −1 src/common/libsubprocess/test/zio.c
  90. +0 −1 src/common/libsubprocess/zio.c
  91. +0 −1 src/common/libsubprocess/zio.h
  92. +3 −2 src/common/libutil/Makefile.am
  93. +0 −1 src/common/libutil/base64_json.c
  94. +0 −1 src/common/libutil/getrusage_json.c
  95. +1 −1 src/common/libutil/shortjson.h
  96. +1 −3 src/common/libutil/tstat.c
  97. +2 −2 src/connectors/local/Makefile.am
  98. +2 −2 src/connectors/local/local.c
  99. +2 −2 src/connectors/loop/Makefile.am
  100. +2 −2 src/connectors/shmem/Makefile.am
  101. +2 −2 src/connectors/shmem/shmem.c
  102. +2 −2 src/connectors/ssh/Makefile.am
  103. +2 −2 src/connectors/ssh/ssh.c
  104. +1 −1 src/modules/Makefile.am
  105. +2 −2 src/modules/aggregator/Makefile.am
  106. +2 −1 src/modules/aggregator/aggregator.c
  107. +3 −3 src/modules/barrier/Makefile.am
  108. +1 −1 src/modules/barrier/libbarrier.c
  109. +2 −2 src/modules/connector-local/Makefile.am
  110. +2 −2 src/modules/content-sqlite/Makefile.am
  111. +2 −2 src/modules/content-sqlite/content-sqlite.c
  112. +2 −2 src/modules/cron/Makefile.am
  113. +1 −1 src/modules/cron/cron.c
  114. +3 −3 src/modules/kvs/Makefile.am
  115. +2 −2 src/modules/kvs/json_dirent.c
  116. +3 −3 src/modules/kvs/kvs.c
  117. +1 −1 src/modules/kvs/kvs_deprecated.h
  118. +12 −12 src/modules/kvs/libkvs.c
  119. +1 −1 src/modules/libjsc/Makefile.am
  120. +1 −1 src/modules/libjsc/jstatctl_deprecated.h
  121. +1 −1 src/modules/libkz/Makefile.am
  122. +0 −1 src/modules/libkz/kz.c
  123. +0 −1 src/modules/libkz/kz.h
  124. +3 −3 src/modules/live/Makefile.am
  125. +2 −2 src/modules/live/liblive.c
  126. +1 −1 src/modules/live/live.c
  127. +3 −2 src/modules/pymod/Makefile.am
  128. +3 −3 src/modules/pymod/py_mod.c
  129. +2 −2 src/modules/resource-hwloc/Makefile.am
  130. +2 −2 src/modules/wreck/Makefile.am
  131. +2 −2 src/modules/wreck/job.c
  132. +0 −1 src/modules/wreck/wrexec.c
  133. +1 −1 src/modules/wreck/wrexecd.c
  134. +2 −2 src/test/Makefile.am
  135. +2 −2 src/test/kap/Makefile.am
  136. +0 −1 src/test/kap/kap_personality.c
  137. +0 −1 src/test/kap/kap_personality.h
  138. +0 −1 src/test/kap/kap_roles.c
  139. +0 −1 src/test/tasyncsock.c
  140. +0 −1 src/test/tbarrier.c
  141. +0 −1 src/test/tmunge.c
  142. +2 −9 t/Makefile.am
  143. +0 −24 t/build/hello.mk
  144. +0 −9 t/build/hello_czmq.c
  145. +0 −11 t/build/hello_flux_core.c
  146. +0 −9 t/build/hello_flux_internal.c
  147. +0 −11 t/build/hello_jsonc.c
  148. +1 −2 t/kvs/commit.c
  149. +1 −1 t/kvs/torture.c
  150. +1 −2 t/kvs/watch.c
  151. +6 −7 t/kvs/watch_disconnect.c
  152. +35 −37 t/loop/multrpc.c
  153. +6 −6 t/loop/rpc.c
  154. +1 −1 t/request/coproc.c
  155. +12 −13 t/request/treq.c
  156. +0 −49 t/t0006-build-basic.t
@@ -38,6 +38,7 @@ addons:
- clang-3.8
- gcc-4.9
- g++-4.9
- libjansson-dev
- lua5.1
- liblua5.1-0-dev
- luarocks
@@ -23,7 +23,8 @@ CODE_COVERAGE_IGNORE_PATTERN = \
"bindings/python/*" \
"common/liblsd/*" \
"common/libutil/sds.*" \
"common/libminilzo/*"
"common/libminilzo/*" \
"common/libjson-c/*"

CODE_COVERAGE_LCOV_OPTIONS =
@CODE_COVERAGE_RULES@
@@ -0,0 +1,114 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_compile_check_sizeof.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_COMPILE_CHECK_SIZEOF(TYPE [, HEADERS [, EXTRA_SIZES...]])
#
# DESCRIPTION
#
# This macro checks for the size of TYPE using compile checks, not run
# checks. You can supply extra HEADERS to look into. the check will cycle
# through 1 2 4 8 16 and any EXTRA_SIZES the user supplies. If a match is
# found, it will #define SIZEOF_`TYPE' to that value. Otherwise it will
# emit a configure time error indicating the size of the type could not be
# determined.
#
# The trick is that C will not allow duplicate case labels. While this is
# valid C code:
#
# switch (0) case 0: case 1:;
#
# The following is not:
#
# switch (0) case 0: case 0:;
#
# Thus, the AC_TRY_COMPILE will fail if the currently tried size does not
# match.
#
# Here is an example skeleton configure.in script, demonstrating the
# macro's usage:
#
# AC_PROG_CC
# AC_CHECK_HEADERS(stddef.h unistd.h)
# AC_TYPE_SIZE_T
# AC_CHECK_TYPE(ssize_t, int)
#
# headers='#ifdef HAVE_STDDEF_H
# #include <stddef.h>
# #endif
# #ifdef HAVE_UNISTD_H
# #include <unistd.h>
# #endif
# '
#
# AX_COMPILE_CHECK_SIZEOF(char)
# AX_COMPILE_CHECK_SIZEOF(short)
# AX_COMPILE_CHECK_SIZEOF(int)
# AX_COMPILE_CHECK_SIZEOF(long)
# AX_COMPILE_CHECK_SIZEOF(unsigned char *)
# AX_COMPILE_CHECK_SIZEOF(void *)
# AX_COMPILE_CHECK_SIZEOF(size_t, $headers)
# AX_COMPILE_CHECK_SIZEOF(ssize_t, $headers)
# AX_COMPILE_CHECK_SIZEOF(ptrdiff_t, $headers)
# AX_COMPILE_CHECK_SIZEOF(off_t, $headers)
#
# LICENSE
#
# Copyright (c) 2008 Kaveh Ghazi <ghazi@caip.rutgers.edu>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.

#serial 5

AU_ALIAS([AC_COMPILE_CHECK_SIZEOF], [AX_COMPILE_CHECK_SIZEOF])
AC_DEFUN([AX_COMPILE_CHECK_SIZEOF],
[changequote(<<, >>)dnl
dnl The name to #define.
define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
dnl The cache variable name.
define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl
changequote([, ])dnl
AC_MSG_CHECKING(size of $1)
AC_CACHE_VAL(AC_CV_NAME,
[for ac_size in 4 8 1 2 16 $3 ; do # List sizes in rough order of prevalence.
AC_TRY_COMPILE([#include "confdefs.h"
#include <sys/types.h>
$2
], [switch (0) case 0: case (sizeof ($1) == $ac_size):;], AC_CV_NAME=$ac_size)
if test x$AC_CV_NAME != x ; then break; fi
done
])
if test x$AC_CV_NAME = x ; then
AC_MSG_ERROR([cannot determine a size for $1])
fi
AC_MSG_RESULT($AC_CV_NAME)
AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The number of bytes in type $1])
undefine([AC_TYPE_NAME])dnl
undefine([AC_CV_NAME])dnl
])
@@ -51,13 +51,30 @@ AC_HEADER_STDC
AC_CHECK_HEADERS( \
pthread.h \
getopt.h \
fcntl.h \
limits.h \
strings.h \
syslog.h \
unistd.h \
[sys/cdefs.h] \
[sys/param.h] \
stdarg.h \
locale.h \
xlocale.h \
endian.h \
inttypes.h \
)

##
# Checks for typedefs, structures, and compiler characteristics
##
AC_C_BIGENDIAN
AC_C_CONST
AC_TYPE_SIZE_T
AX_COMPILE_CHECK_SIZEOF(int)
AX_COMPILE_CHECK_SIZEOF(long)
AX_COMPILE_CHECK_SIZEOF(size_t, [#include <stdint.h>])


##
# Checks for library functions
@@ -66,6 +83,18 @@ AC_CHECK_FUNCS( \
getopt_long \
vsnprintf \
vsscanf \
realloc \
strcasecmp \
strdup \
strerror \
snprintf \
vsnprintf \
vasprintf \
open \
vsyslog \
strncasecmp \
setlocale \
uselocale \
)
X_AC_CHECK_PTHREADS
X_AC_CHECK_COND_LIB(util, forkpty)
@@ -109,8 +138,7 @@ AX_LUA_HEADERS
AX_LUA_LIBS
X_AC_ZEROMQ
X_AC_MUNGE
PKG_CHECK_MODULES([JSON], [json], [],
[PKG_CHECK_MODULES([JSON], [json-c])])
PKG_CHECK_MODULES([JANSSON], [jansson], [], [])
PKG_CHECK_MODULES([HWLOC], [hwloc >= 1.4], [], [])
PKG_CHECK_MODULES([SQLITE], [sqlite3], [], [])
LX_FIND_MPI
@@ -191,6 +219,7 @@ AC_CONFIG_FILES( \
src/common/libtap/Makefile \
src/common/liblsd/Makefile \
src/common/libutil/Makefile \
src/common/libjson-c/Makefile \
src/common/libev/Makefile \
src/common/libminilzo/Makefile \
src/common/libpmi/Makefile \
@@ -222,11 +251,11 @@ AC_CONFIG_FILES( \
src/modules/resource-hwloc/Makefile \
src/modules/cron/Makefile \
src/modules/aggregator/Makefile \
src/modules/pymod/Makefile \
src/test/Makefile \
src/test/kap/Makefile \
etc/Makefile \
etc/flux-core.pc \
etc/Makefile.inc \
doc/Makefile \
doc/man1/Makefile \
doc/man3/Makefile \
@@ -53,7 +53,10 @@ MAN3_FILES_SECONDARY = \
flux_rpc_destroy.3 \
flux_rpc_check.3 \
flux_rpc_get.3 \
flux_rpc_completed.3 \
flux_rpc_next.3 \
flux_rpc_get_nodeid.3 \
flux_rpcf.3 \
flux_rpc_getf.3 \
flux_reduce_destroy.3 \
flux_reduce_append.3 \
flux_reduce_pop.3 \
@@ -123,8 +126,11 @@ flux_msg_decode.3: flux_msg_encode.3
flux_msg_recvfd.3: flux_msg_sendfd.3
flux_rpc_destroy.3: flux_rpc.3
flux_rpc_get.3: flux_rpc.3
flux_rpc_getf.3: flux_rpc.3
flux_rpcf.3: flux_rpc.3
flux_rpc_check.3: flux_rpc_then.3
flux_rpc_completed.3: flux_rpc_multi.3
flux_rpc_next.3: flux_rpc_multi.3
flux_rpc_get_nodeid.3: flux_rpc_multi.3
flux_reduce_destroy.3: flux_reduce_create.3
flux_reduce_append.3: flux_reduce_create.3
flux_reduce_pop.3: flux_reduce_create.3
@@ -184,12 +190,12 @@ AM_LDFLAGS = \

AM_CPPFLAGS = \
-I$(top_srcdir) -I$(top_srcdir)/src/include \
$(JSON_CFLAGS) $(ZMQ_CFLAGS)
$(ZMQ_CFLAGS)

LDADD = \
$(top_builddir)/src/common/libflux-internal.la \
$(top_builddir)/src/common/libflux-core.la \
$(JSON_LIBS) $(ZMQ_LIBS) $(LIBPTHREAD)
$(ZMQ_LIBS) $(LIBPTHREAD)

check_PROGRAMS = \
topen \
@@ -5,7 +5,7 @@ flux_rpc(3)

NAME
----
flux_rpc, flux_rpc_get, flux_rpc_destroy - perform a remote procedure call to a Flux service
flux_rpc, flux_rpcf, flux_rpc_get, flux_rpc_getf, flux_rpc_destroy - perform a remote procedure call to a Flux service


SYNOPSIS
@@ -16,10 +16,16 @@ SYNOPSIS
const char *json_in,
uint32_t nodeid_in, int flags);

flux_rpc_t *flux_rpcf (flux_t *h, const char *topic,
uint32_t nodeid_in, int flags,
const char *fmt, ...);


void flux_rpc_destroy (flux_rpc_t *rpc);

int flux_rpc_get (flux_rpc_t *rpc, uint32_t *nodeid_out,
const char **json_out);
int flux_rpc_get (flux_rpc_t *rpc, const char **json_out);

int flux_rpc_getf (flux_rpc_t *rpc, const char *fmt, ...);


DESCRIPTION
@@ -68,14 +74,24 @@ by a NULL _json_out_) arrives. The storage associated with _json_out_
belongs to the flux_rpc_t object and is invalidated when that object is
destroyed.
_nodeid_out_, if non-NULL, is set to the _nodeid_in_ argument given
to `flux_rpc()`. This is primarily useful with `flux_rpc_multi(3)`.
`flux_rpc_destroy()` destroys a completed `flux_rpc_t`, invalidating
payload as described above, and freeing the RPC matchtag. Destroying
an RPC before completion renders the matchtag associated with the RPC
unusable; it is effectively leaked from the matchtag pool.
`flux_rpcf()` is a variant of `flux_rpc()` that constructs a JSON
payload based on the provided `fmt` string and variable arguments.
The `fmt` string and variable arguments are passed internally to
jansson's `json_pack()` function. See jansson documentation for
details.
`flux_rpc_getf()` is a variant of `flux_rpc_get()` that parses a JSON
payload based on the provided `fmt` string and variable arguments.
The `fmt` string and variable arguments are passed internally to
jansson's `json_unpack()` function. Any strings or objects returned
are invalidated when `flux_rpc_destroy()` is called. See jansson
documentation for details.
CANCELLATION
------------
@@ -5,7 +5,7 @@ flux_rpc_multi(3)

NAME
----
flux_rpc_multi, flux_rpc_completed, - send a remote procedure call to a Flux service on multiple ranks
flux_rpc_multi, flux_rpc_next, flux_rpc_get_nodeid - send a remote procedure call to a Flux service on multiple ranks


SYNOPSIS
@@ -15,7 +15,9 @@ SYNOPSIS
flux_rpc_t *flux_rpc_multi (flux_t *h, const char *topic, const char *json_str,
const char *nodeset, int flags);
bool flux_rpc_completed (flux_rpc_t *rpc);
int flux_rpc_next (flux_rpc_t *rpc);
int flux_rpc_get_nodeid (flux_t *h, uint32_t *nodeid);
DESCRIPTION
-----------
@@ -45,32 +47,36 @@ No response is expected. The request will not be assigned a matchtag,
and the flux_rpc_t returned by `flux_rpc()` may be immediately destroyed.
`flux_rpc_get()` blocks until a matching response is received, then
decodes the result. This function is called once for each response,
each time invalidating the payload obtained in the previous call.
For asynchronous response handling, see flux_rpc_then(3).
decodes the result. For asynchronous response handling,
see flux_rpc_then(3).
`flux_rpc_completed()` returns true once all the RPC responses have been
received and handled via `flux_rpc_get()`. It can be used to terminate
synchronous response collection, e.g.
`flux_rpc_next()` invalidates the last-received message and payload
returned by `flux_rpc_get()`, and returns 0 if more responses are received.
Once all responses have been received, `flux_rpc_next()` returns -1;
thus it may be used as the conditional on a do-while loop, e.g.
....
while (!flux_rpc_completed (rpc))
flux_rpc_get (rpc, &nodeid, &payload);
do {
flux_rpc_get (rpc, &payload);
} while (flux_rpc_next (rpc) == 0);
....
`flux_rpc_destroy()` destroys a completed `flux_rpc_t`, invalidating
payload as described above, and freeing the RPC matchtag block. Destroying
an RPC before completion renders the matchtag block associated with the RPC
unusable; it is effectively leaked from the matchtag pool.
`flux_rpc_get_nodeid()` blocks until a matching response is received, then
decodes the nodeid in the response message. If the remote service returned
a response containing an error, `flux_rpc_get_nodeid()` will succeed,
while `flux_rpc_get()` will fail. This allows the failing nodeid to
be determined.
RETURN VALUE
------------
`flux_rpc_multi()` returns a flux_rpc_t object on success. On error, NULL
is returned, and errno is set appropriately.
`flux_rpc_completed()` returns true if the RPC has completed, else false.
It does not report any errors.
`flux_rpc_next()` returns 0 if additional responses are expected, else -1.
It does not set errno.
`flux_rpc_get_nodeid()` returns 0 on success; on failure, it returns -1
and sets errno appropriately.
ERRORS
@@ -8,7 +8,7 @@ void get_rank (flux_rpc_t *rpc)
json_object *o;
const char *rank;

if (flux_rpc_get (rpc, NULL, &json_str) < 0)
if (flux_rpc_get (rpc, &json_str) < 0)
log_err_exit ("flux_rpc_get");
if (!(o = Jfromstr (json_str)) || !Jget_str (o, "value", &rank))
log_msg_exit ("response protocol error");
@@ -8,7 +8,7 @@ void get_rank (flux_rpc_t *rpc, void *arg)
json_object *o;
const char *rank;

if (flux_rpc_get (rpc, NULL, &json_str) < 0)
if (flux_rpc_get (rpc, &json_str) < 0)
log_err_exit ("flux_rpc_get");
if (!(o = Jfromstr (json_str)) || !Jget_str (o, "value", &rank))
log_msg_exit ("response protocol error");
Oops, something went wrong.

0 comments on commit 286b6e7

Please sign in to comment.
You can’t perform that action at this time.