/* Received response message from broker. * Look up the sender uuid in clients hash and deliver. * Responses for disconnected clients are silently discarded. */ static void response_cb (flux_t h, flux_msg_watcher_t *w, const flux_msg_t *msg, void *arg) { ctx_t *ctx = arg; char *uuid = NULL; client_t *c; flux_msg_t *cpy = flux_msg_copy (msg, true); if (!cpy) oom (); if (flux_msg_pop_route (cpy, &uuid) < 0) goto done; if (flux_msg_clear_route (cpy) < 0) goto done; c = zlist_first (ctx->clients); while (c) { if (!strcmp (uuid, zuuid_str (c->uuid))) { if (client_send_nocopy (c, &cpy) < 0) { /* FIXME handle errors */ flux_log (h, LOG_ERR, "%s: client_send %s: %s", __FUNCTION__, zuuid_str (c->uuid), strerror (errno)); errno = 0; } break; } c = zlist_next (ctx->clients); } if (uuid) free (uuid); done: flux_msg_destroy (cpy); }
/* N.B. if a new message arrives with an unconsumed one in the rpc handle, * push the new one back to to the receive queue so it will trigger another * reactor callback and handle the cached one now. * The reactor will repeatedly call the continuation (level-triggered) * until all received responses are consumed. */ static void rpc_cb (flux_t h, flux_msg_handler_t *w, const flux_msg_t *msg, void *arg) { flux_rpc_t *rpc = arg; assert (rpc->then_cb != NULL); flux_rpc_usecount_incr (rpc); if (rpc->rx_msg) { if (flux_requeue (rpc->h, msg, FLUX_RQ_HEAD) < 0) goto done; } else { if (!(rpc->rx_msg = flux_msg_copy (msg, true))) goto done; } rpc->then_cb (rpc, rpc->then_arg); if (rpc->rx_msg) { if (flux_requeue (rpc->h, rpc->rx_msg, FLUX_RQ_HEAD) < 0) goto done; rpc->rx_msg = NULL; } done: /* no good way to report flux_requeue() errors */ if (flux_rpc_completed (rpc)) flux_msg_handler_stop (rpc->w); flux_rpc_usecount_decr (rpc); }
static int op_send (void *impl, const flux_msg_t *msg, int flags) { ctx_t *c = impl; assert (c->magic == CTX_MAGIC); int type; flux_msg_t *cpy = NULL; int rc = -1; if (!(cpy = flux_msg_copy (msg, true))) goto done; if (flux_msg_get_type (cpy, &type) < 0) goto done; switch (type) { case FLUX_MSGTYPE_REQUEST: case FLUX_MSGTYPE_EVENT: if (flux_msg_enable_route (cpy) < 0) goto done; if (flux_msg_push_route (cpy, fake_uuid) < 0) goto done; break; } if (msglist_append (c->queue, cpy) < 0) goto done; cpy = NULL; /* c->queue now owns cpy */ rc = 0; done: if (cpy) flux_msg_destroy (cpy); return rc; }
static int barrier_add_client (barrier_t *b, char *sender, const flux_msg_t *msg) { flux_msg_t *cpy = flux_msg_copy (msg, true); if (!cpy || zhash_insert (b->clients, sender, cpy) < 0) return -1; zhash_freefn (b->clients, sender, (zhash_free_fn *)flux_msg_destroy); return 0; }
/* Don't reply to request - just queue it for later. */ void clog_request_cb (flux_t h, flux_msg_handler_t *w, const flux_msg_t *msg, void *arg) { ctx_t *ctx = getctx (h); flux_msg_t *cpy = flux_msg_copy (msg, true); if (zlist_push (ctx->clog_requests, cpy) < 0) oom (); }
int module_sendmsg (module_t *p, const flux_msg_t *msg) { flux_msg_t *cpy = NULL; int type; int rc = -1; if (!msg) return 0; if (flux_msg_get_type (msg, &type) < 0) goto done; switch (type) { case FLUX_MSGTYPE_REQUEST: { /* simulate DEALER socket */ char uuid[16]; snprintf (uuid, sizeof (uuid), "%u", p->rank); if (!(cpy = flux_msg_copy (msg, true))) goto done; if (flux_msg_push_route (cpy, uuid) < 0) goto done; if (flux_msg_sendzsock (p->sock, cpy) < 0) goto done; break; } case FLUX_MSGTYPE_RESPONSE: { /* simulate ROUTER socket */ if (!(cpy = flux_msg_copy (msg, true))) goto done; if (flux_msg_pop_route (cpy, NULL) < 0) goto done; if (flux_msg_sendzsock (p->sock, cpy) < 0) goto done; break; } default: if (flux_msg_sendzsock (p->sock, msg) < 0) goto done; break; } rc = 0; done: flux_msg_destroy (cpy); return rc; }
/* Proxy ping. */ void xping_request_cb (flux_t h, flux_msg_handler_t *w, const flux_msg_t *msg, void *arg) { ctx_t *ctx = arg; const char *json_str; int saved_errno; int rank, seq = ctx->ping_seq++; const char *service; char *hashkey = NULL; JSON in = Jnew (); JSON o = NULL; flux_msg_t *cpy; if (flux_request_decode (msg, NULL, &json_str) < 0) { saved_errno = errno; goto error; } if (!(o = Jfromstr (json_str)) || !Jget_int (o, "rank", &rank) || !Jget_str (o, "service", &service)) { saved_errno = errno = EPROTO; goto error; } flux_log (h, LOG_DEBUG, "Rxping rank=%d service=%s", rank, service); Jadd_int (in, "seq", seq); flux_log (h, LOG_DEBUG, "Tping seq=%d %d!%s", seq, rank, service); flux_rpc_t *rpc; if (!(rpc = flux_rpc (h, service, Jtostr (in), rank, FLUX_RPC_NORESPONSE))) { saved_errno = errno; goto error; } flux_rpc_destroy (rpc); if (!(cpy = flux_msg_copy (msg, true))) { saved_errno = errno; goto error; } hashkey = xasprintf ("%d", seq); zhash_update (ctx->ping_requests, hashkey, cpy); zhash_freefn (ctx->ping_requests, hashkey, (zhash_free_fn *)flux_msg_destroy); Jput (o); Jput (in); if (hashkey) free (hashkey); return; error: if (flux_respond (h, msg, saved_errno, NULL) < 0) flux_log_error (h, "%s: flux_respond", __FUNCTION__); Jput (o); Jput (in); }
static int client_send (client_t *c, const flux_msg_t *msg) { flux_msg_t *cpy = flux_msg_copy (msg, true); int rc; if (!cpy) { errno = ENOMEM; return -1; } rc = client_send_nocopy (c, &cpy); flux_msg_destroy (cpy); return rc; }
wait_t *wait_create (flux_t h, flux_msg_handler_t *wh, const flux_msg_t *msg, flux_msg_handler_f cb, void *arg) { wait_t *w = xzmalloc (sizeof (*w)); w->magic = WAIT_MAGIC; w->hand.cb = cb; w->hand.arg = arg; w->hand.h = h; w->hand.w = wh; if (!(w->hand.msg = flux_msg_copy (msg, true))) { wait_destroy (w, NULL); errno = ENOMEM; return NULL; } monotime (&w->t0); return w; }
wait_t *wait_create_msg_handler (flux_t *h, flux_msg_handler_t *wh, const flux_msg_t *msg, flux_msg_handler_f cb, void *arg) { wait_t *w = wait_create (NULL, NULL); if (w) { w->hand.cb = cb; w->hand.arg = arg; w->hand.h = h; w->hand.w = wh; if (msg && !(w->hand.msg = flux_msg_copy (msg, true))) { wait_destroy (w); errno = ENOMEM; return NULL; } } return w; }
/* Internal callback for matching response. * For the multi-response case, overwrite previous message if * flux_rpc_next () was not called. */ static void rpc_cb (flux_t *h, flux_msg_handler_t *w, const flux_msg_t *msg, void *arg) { flux_rpc_t *rpc = arg; assert (rpc->then_cb != NULL); flux_rpc_usecount_incr (rpc); if (rpc->rx_msg || rpc->rx_errnum) (void)flux_rpc_next (rpc); if (!(rpc->rx_msg = flux_msg_copy (msg, true))) goto done; rpc->rx_count++; rpc->then_cb (rpc, rpc->then_arg); done: if (rpc->rx_count >= rpc->rx_expected || flux_fatality (rpc->h)) flux_msg_handler_stop (rpc->w); flux_rpc_usecount_decr (rpc); }
int publisher_send (struct publisher *pub, const flux_msg_t *msg) { flux_msg_t *cpy; if (!(cpy = flux_msg_copy (msg, true))) return -1; if (flux_msg_clear_route (cpy) < 0) goto error; if (flux_msg_set_seq (cpy, ++pub->seq) < 0) goto error_restore_seq; send_event (pub, cpy); flux_msg_destroy (cpy); return 0; error_restore_seq: pub->seq--; error: flux_msg_destroy (cpy); return -1; }
static int op_send (void *impl, const flux_msg_t *msg, int flags) { ctx_t *c = impl; assert (c->magic == CTX_MAGIC); int type; flux_msg_t *cpy = NULL; int rc = -1; if (!(cpy = flux_msg_copy (msg, true))) goto done; if (flux_msg_get_type (cpy, &type) < 0) goto done; if (msglist_append (c->queue, cpy) < 0) goto done; cpy = NULL; /* c->queue now owns cpy */ rc = 0; done: if (cpy) flux_msg_destroy (cpy); return rc; }
static int op_send (void *impl, const flux_msg_t *msg, int flags) { ctx_t *ctx = impl; assert (ctx->magic == MODHANDLE_MAGIC); flux_msg_t *cpy = NULL; int type; int rc = -1; if (connect_socket (ctx) < 0) goto done; if (flux_msg_get_type (msg, &type) < 0) goto done; switch (type) { case FLUX_MSGTYPE_REQUEST: case FLUX_MSGTYPE_EVENT: if (!(cpy = flux_msg_copy (msg, true))) goto done; if (flux_msg_enable_route (cpy) < 0) goto done; if (flux_msg_push_route (cpy, ctx->uuid) < 0) goto done; if (flux_msg_sendzsock (ctx->sock, cpy) < 0) goto done; break; case FLUX_MSGTYPE_RESPONSE: case FLUX_MSGTYPE_KEEPALIVE: if (flux_msg_sendzsock (ctx->sock, msg) < 0) goto done; break; default: errno = EINVAL; goto done; } rc = 0; done: flux_msg_destroy (cpy); return rc; }
/* FIXME: FLUX_O_TRACE will show these messages being received again * So will message counters. */ int flux_requeue (flux_t h, const flux_msg_t *msg, int flags) { flux_msg_t *cpy; int rc; if (flags != FLUX_RQ_TAIL && flags != FLUX_RQ_HEAD) { errno = EINVAL; goto fatal; } if (!(cpy = flux_msg_copy (msg, true))) goto fatal; if (flags == FLUX_RQ_TAIL) rc = msglist_append (h->queue, cpy); else rc = msglist_push (h->queue, cpy); if (rc < 0) { flux_msg_destroy (cpy); goto fatal; } return 0; fatal: FLUX_FATAL (h); return -1; }
/* Send shutdown request, broker to module. */ int module_stop (module_t *p, const flux_msg_t *rmmod) { assert (p->magic == MODULE_MAGIC); char *topic = xasprintf ("%s.shutdown", p->name); flux_msg_t *msg; int rc = -1; if (!(msg = flux_msg_create (FLUX_MSGTYPE_REQUEST))) goto done; if (flux_msg_set_topic (msg, topic) < 0) goto done; if (flux_msg_sendzsock (p->sock, msg) < 0) goto done; if (rmmod) { flux_msg_t *cpy = flux_msg_copy (rmmod, true); if (!cpy || zlist_append (p->rmmod, cpy) < 0) oom (); } rc = 0; done: free (topic); flux_msg_destroy (msg); return rc; }