static int rpc_get (flux_rpc_t *rpc) { int rc = -1; if (rpc->rx_errnum) { errno = rpc->rx_errnum; goto done; } if (!rpc->rx_msg && !rpc->rx_errnum) { #if HAVE_CALIPER cali_begin_string_byname("flux.message.rpc", "single"); #endif if (!(rpc->rx_msg = flux_recv (rpc->h, rpc->m, 0))) { rpc->rx_errnum = errno; goto done; } #if HAVE_CALIPER cali_end_byname("flux.message.rpc"); #endif rpc->rx_count++; } rc = 0; done: return rc; }
void test_nsrc (flux_t *h, uint32_t nodeid) { flux_future_t *f; const int count = 10000; json_object *in = Jnew (); const char *json_str; json_object *out = NULL; int i, seq; Jadd_int (in, "count", count); if (!(f = flux_rpc (h, "req.nsrc", Jtostr (in), FLUX_NODEID_ANY, FLUX_RPC_NORESPONSE))) log_err_exit ("%s", __FUNCTION__); flux_future_destroy (f); for (i = 0; i < count; i++) { flux_msg_t *msg = flux_recv (h, FLUX_MATCH_ANY, 0); if (!msg) log_err_exit ("%s", __FUNCTION__); if (flux_response_decode (msg, NULL, &json_str) < 0) log_msg_exit ("%s: decode %d", __FUNCTION__, i); if (!json_str || !(out = Jfromstr (json_str)) || !Jget_int (out, "seq", &seq)) log_msg_exit ("%s: decode %d payload", __FUNCTION__, i); if (seq != i) log_msg_exit ("%s: decode %d - seq mismatch %d", __FUNCTION__, i, seq); Jput (out); flux_msg_destroy (msg); } Jput (in); }
void test_nsrc (flux_t *h, uint32_t nodeid) { flux_future_t *f; const char *json_str; const int count = 10000; int i, seq = -1; json_t *o; if (!(f = flux_rpc_pack (h, "req.nsrc", FLUX_NODEID_ANY, FLUX_RPC_NORESPONSE, "{s:i}", "count", count))) log_err_exit ("%s", __FUNCTION__); flux_future_destroy (f); for (i = 0; i < count; i++) { flux_msg_t *msg; if (!(msg = flux_recv (h, FLUX_MATCH_ANY, 0))) log_err_exit ("%s", __FUNCTION__); if (flux_response_decode (msg, NULL, &json_str) < 0) log_msg_exit ("%s: decode %d", __FUNCTION__, i); if (!json_str || !(o = json_loads (json_str, 0, NULL)) || json_unpack (o, "{s:i}", "seq", &seq) < 0) log_msg_exit ("%s: decode %d payload", __FUNCTION__, i); if (seq != i) log_msg_exit ("%s: decode %d - seq mismatch %d", __FUNCTION__, i, seq); json_decref (o); flux_msg_destroy (msg); } }
int flux_rpc_get (flux_rpc_t *rpc, uint32_t *nodeid, const char **json_str) { int rc = -1; if (rpc->oneway) { errno = EINVAL; goto done; } if (!rpc->rx_msg && !(rpc->rx_msg = flux_recv (rpc->h, rpc->m, 0))) goto done; flux_msg_destroy (rpc->rx_msg_consumed); /* invalidate last-got payload */ rpc->rx_msg_consumed = rpc->rx_msg; rpc->rx_msg = NULL; rpc->rx_count++; if (nodeid) { uint32_t matchtag; if (flux_msg_get_matchtag (rpc->rx_msg_consumed, &matchtag) < 0) goto done; *nodeid = lookup_nodeid (rpc, matchtag); } if (flux_response_decode (rpc->rx_msg_consumed, NULL, json_str) < 0) goto done; rc = 0; done: return rc; }
bool flux_rpc_check (flux_rpc_t *rpc) { if (rpc->oneway) return false; if (rpc->rx_msg || (rpc->rx_msg = flux_recv (rpc->h, rpc->m, FLUX_O_NONBLOCK))) return true; errno = 0; return false; }
static void wait_for_event (flux_t h, int64_t id, char *topic) { struct flux_match match = { .typemask = FLUX_MSGTYPE_EVENT, .matchtag = FLUX_MATCHTAG_NONE, }; match.topic_glob = topic; flux_msg_t *msg = flux_recv (h, match, 0); flux_msg_destroy (msg); return; }
/* This test is to make sure that deferred responses are handled in order. * Arrange for module to source 10K sequenced responses. Messages 5000-5499 * are "put back" on the handle using flux_putmsg(). We ensure that * the 10K messages are nonetheless received in order. */ void test_putmsg (flux_t *h, uint32_t nodeid) { flux_future_t *f; const char *json_str; const int count = 10000; const int defer_start = 5000; const int defer_count = 500; json_object *in = Jnew (); json_object *out = NULL; int seq, myseq = 0; zlist_t *defer = zlist_new (); bool popped = false; flux_msg_t *z; if (!defer) oom (); Jadd_int (in, "count", count); if (!(f = flux_rpc (h, "req.nsrc", Jtostr (in), FLUX_NODEID_ANY, FLUX_RPC_NORESPONSE))) log_err_exit ("%s", __FUNCTION__); flux_future_destroy (f); do { flux_msg_t *msg = flux_recv (h, FLUX_MATCH_ANY, 0); if (!msg) log_err_exit ("%s", __FUNCTION__); if (flux_response_decode (msg, NULL, &json_str) < 0) log_msg_exit ("%s: decode", __FUNCTION__); if (!json_str || !(out = Jfromstr (json_str)) || !Jget_int (out, "seq", &seq)) log_msg_exit ("%s: decode - payload", __FUNCTION__); Jput (out); if (seq >= defer_start && seq < defer_start + defer_count && !popped) { if (zlist_append (defer, msg) < 0) oom (); if (seq == defer_start + defer_count - 1) { while ((z = zlist_pop (defer))) { if (flux_requeue (h, z, FLUX_RQ_TAIL) < 0) log_err_exit ("%s: flux_requeue", __FUNCTION__); flux_msg_destroy (z); } popped = true; } continue; } if (seq != myseq) log_msg_exit ("%s: expected %d got %d", __FUNCTION__, myseq, seq); myseq++; flux_msg_destroy (msg); } while (myseq < count); zlist_destroy (&defer); Jput (in); }
int main (int argc, char *argv[]) { flux_t *h; flux_msg_t *msg; const char *topic; const char *reason; int flags; plan (NO_PLAN); if (!(h = loopback_create (0))) BAIL_OUT ("loopback_create failed"); /* Send request */ ok (flux_panic (h, 0, 0, "fubar") == 0, "flux_panic works"); /* Receive request on the loopback */ msg = flux_recv (h, FLUX_MATCH_ANY, 0); ok (msg != NULL, "flux_recv received message on loop"); ok (flux_request_unpack (msg, &topic, "{s:s s:i}", "reason", &reason, "flags", &flags) == 0, "flux_request_unpack worked on panic request"); ok (topic != NULL && !strcmp (topic, "cmb.panic"), "topic string is correct"); ok (!strcmp (reason, "fubar"), "reason is correct"); ok (flags == 0, "flags is correct"); flux_msg_destroy (msg); /* invalid arguments */ errno = 0; ok (flux_panic (NULL, 0, 0, "foo") < 0 && errno == EINVAL, "flux_panic h=NULL fails with EINVAL"); errno = 0; ok (flux_panic (h, 0, 1, "foo") < 0 && errno == EINVAL, "flux_panic flags=1 fails with EINVAL"); errno = 0; ok (flux_panic (h, 0, 0, NULL) < 0 && errno == EINVAL, "flux_panic reason=NULL fails with EINVAL"); flux_close (h); done_testing(); return (0); }
/* This test is to make sure that deferred responses are handled in order. * Arrange for module to source 10K sequenced responses. Messages 5000-5499 * are "put back" on the handle using flux_putmsg(). We ensure that * the 10K messages are nonetheless received in order. */ void test_putmsg (flux_t *h, uint32_t nodeid) { flux_future_t *f; const char *json_str; const int count = 10000; const int defer_start = 5000; const int defer_count = 500; int seq, myseq = 0; zlist_t *defer = zlist_new (); bool popped = false; flux_msg_t *z; json_t *o; if (!defer) oom (); if (!(f = flux_rpc_pack (h, "req.nsrc", FLUX_NODEID_ANY, FLUX_RPC_NORESPONSE, "{s:i}", "count", count))) log_err_exit ("%s", __FUNCTION__); flux_future_destroy (f); do { flux_msg_t *msg = flux_recv (h, FLUX_MATCH_ANY, 0); if (!msg) log_err_exit ("%s", __FUNCTION__); if (flux_response_decode (msg, NULL, &json_str) < 0) log_msg_exit ("%s: decode", __FUNCTION__); if (!json_str || !(o = json_loads (json_str, 0, NULL)) || json_unpack (o, "{s:i}", "seq", &seq) < 0) log_msg_exit ("%s: decode - payload", __FUNCTION__); json_decref (o); if (seq >= defer_start && seq < defer_start + defer_count && !popped) { if (zlist_append (defer, msg) < 0) oom (); if (seq == defer_start + defer_count - 1) { while ((z = zlist_pop (defer))) { if (flux_requeue (h, z, FLUX_RQ_TAIL) < 0) log_err_exit ("%s: flux_requeue", __FUNCTION__); flux_msg_destroy (z); } popped = true; } continue; } if (seq != myseq) log_msg_exit ("%s: expected %d got %d", __FUNCTION__, myseq, seq); myseq++; flux_msg_destroy (msg); } while (myseq < count); zlist_destroy (&defer); }
bool flux_rpc_check (flux_rpc_t *rpc) { assert (rpc->magic == RPC_MAGIC); if (rpc->rx_msg || rpc->rx_errnum) return true; if (!(rpc->rx_msg = flux_recv (rpc->h, rpc->m, FLUX_O_NONBLOCK))) { if (errno == EAGAIN || errno == EWOULDBLOCK) { errno = 0; return false; } else rpc->rx_errnum = errno; } return (rpc->rx_msg || rpc->rx_errnum); }
static int coproc_cb (coproc_t *c, void *arg) { flux_msg_handler_t *w = arg; flux_msg_t *msg; int type; int rc = -1; if (!(msg = flux_recv (w->d->h, FLUX_MATCH_ANY, FLUX_O_NONBLOCK))) { if (errno == EAGAIN || errno == EWOULDBLOCK) rc = 0; goto done; } if (flux_msg_get_type (msg, &type) < 0) goto done; w->fn (w->d->h, w, msg, w->arg); rc = 0; done: flux_msg_destroy (msg); return rc; }
int main (int argc, char **argv) { flux_t *h; flux_msg_t *msg; const char *topic; if (!(h = flux_open (NULL, 0))) log_err_exit ("flux_open"); if (flux_event_subscribe (h, "hb") < 0) log_err_exit ("flux_event_subscribe"); if (!(msg = flux_recv (h, FLUX_MATCH_EVENT, 0))) log_err_exit ("flux_recv"); if (flux_msg_get_topic (msg, &topic) < 0) log_err_exit ("flux_msg_get_topic"); printf ("Event: %s\n", topic); if (flux_event_unsubscribe (h, "hb") < 0) log_err_exit ("flux_event_unsubscribe"); flux_msg_destroy (msg); flux_close (h); return (0); }
static void handle_cb (flux_reactor_t *r, flux_watcher_t *hw, int revents, void *arg) { struct dispatch *d = arg; flux_msg_handler_t *w; flux_msg_t *msg = NULL; int type; if (revents & FLUX_POLLERR) goto fatal; if (!(msg = flux_recv (d->h, FLUX_MATCH_ANY, FLUX_O_NONBLOCK))) { if (errno != EAGAIN && errno != EWOULDBLOCK) goto fatal; else goto done; } if (flux_msg_get_type (msg, &type) < 0) goto done; /* Message matches a coproc that yielded. * Resume, arranging for msg to be returned next by flux_recv(). */ if ((w = find_waiting_handler (d, msg))) { if (flux_requeue (d->h, msg, FLUX_RQ_HEAD) < 0) goto fatal; zlist_remove (d->waiters, w); if (resume_coproc (w) < 0) goto fatal; /* Message matches a handler. * If coproc already running, queue message as backlog. * Else if FLUX_O_COPROC, start coproc. * If coprocs not enabled, call handler directly. */ } else if ((w = find_handler (d, msg))) { if (w->coproc && coproc_started (w->coproc)) { if (backlog_append (w, &msg) < 0) /* msg now property of backlog */ goto fatal; } else if ((flux_flags_get (d->h) & FLUX_O_COPROC)) { if (flux_requeue (d->h, msg, FLUX_RQ_HEAD) < 0) goto fatal; if (start_coproc (w) < 0) goto fatal; } else { w->fn (d->h, w, msg, w->arg); } /* Message matched nothing. * Respond with ENOSYS if it was a request. * Else log it if FLUX_O_TRACE */ } else { if (type == FLUX_MSGTYPE_REQUEST) { if (flux_respond (d->h, msg, ENOSYS, NULL)) goto done; } else if (flux_flags_get (d->h) & FLUX_O_TRACE) { const char *topic = NULL; (void)flux_msg_get_topic (msg, &topic); fprintf (stderr, "nomatch: %s '%s'\n", flux_msg_typestr (type), topic ? topic : ""); } } done: flux_msg_destroy (msg); return; fatal: flux_msg_destroy (msg); flux_reactor_stop_error (r); FLUX_FATAL (d->h); }