Ejemplo n.º 1
0
int flux_event_unsubscribe (flux_t h, const char *topic)
{
    if (h->ops->event_unsubscribe) {
        if (h->ops->event_unsubscribe (h->impl, topic) < 0)
            goto fatal;
    }
    return 0;
fatal:
    FLUX_FATAL (h);
    return -1;
}
Ejemplo n.º 2
0
int flux_send (flux_t h, const flux_msg_t *msg, int flags)
{
    if (!h->ops->send) {
        errno = ENOSYS;
        goto fatal;
    }
    flags |= h->flags;
    update_tx_stats (h, msg);
    if (flags & FLUX_O_TRACE)
        flux_msg_fprint (stderr, msg);
    if (h->ops->send (h->impl, msg, flags) < 0)
        goto fatal;
#if HAVE_CALIPER
    profiling_msg_snapshot(h, msg, flags, "send");
#endif
    return 0;
fatal:
    FLUX_FATAL (h);
    return -1;
}
Ejemplo n.º 3
0
/* 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;
}
Ejemplo n.º 4
0
int flux_pollfd (flux_t h)
{
    if (h->pollfd < 0) {
        struct epoll_event ev = {
            .events = EPOLLET | EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP,
        };
        if ((h->pollfd = epoll_create1 (EPOLL_CLOEXEC)) < 0)
            goto fatal;
        /* add queue pollfd */
        ev.data.fd = msglist_pollfd (h->queue);
        if (ev.data.fd < 0)
            goto fatal;
        if (epoll_ctl (h->pollfd, EPOLL_CTL_ADD, ev.data.fd, &ev) < 0)
            goto fatal;
        /* add connector pollfd (if defined) */
        if (h->ops->pollfd) {
            ev.data.fd = h->ops->pollfd (h->impl);
            if (ev.data.fd < 0)
                goto fatal;
            if (epoll_ctl (h->pollfd, EPOLL_CTL_ADD, ev.data.fd, &ev) < 0)
                goto fatal;
        }
    }
    return h->pollfd;
fatal:
    if (h->pollfd >= 0) {
        (void)close (h->pollfd);
        h->pollfd = -1;
    }
    FLUX_FATAL (h);
    return -1;
}

int flux_pollevents (flux_t h)
{
    int e, events = 0;

    /* wait for handle event */
    if (h->pollfd >= 0) {
        struct epoll_event ev;
        (void)epoll_wait (h->pollfd, &ev, 1, 0);
    }
    /* get connector events (if applicable) */
    if (h->ops->pollevents) {
        if ((events = h->ops->pollevents (h->impl)) < 0)
            goto fatal;
    }
    /* get queue events */
    if ((e = msglist_pollevents (h->queue)) < 0)
        goto fatal;
    if ((e & POLLIN))
        events |= FLUX_POLLIN;
    if ((e & POLLOUT))
        events |= FLUX_POLLOUT;
    if ((e & POLLERR))
        events |= FLUX_POLLERR;
    return events;
fatal:
    FLUX_FATAL (h);
    return -1;
}
Ejemplo n.º 5
0
/* If this function is called without the NONBLOCK flag from a reactor
 * handler running in coprocess context, the call to flux_sleep_on()
 * will allow the reactor to run until a message matching 'match' arrives.
 * The flux_sleep_on() call will then resume, and the next call to recv()
 * will return the matching message.  If not running in coprocess context,
 * flux_sleep_on() will fail with EINVAL.  In that case, the do loop
 * reading messages and comparing them to match criteria may have to read
 * a few non-matching messages before finding a match.  On return, those
 * non-matching messages have to be requeued in the handle, hence the
 * defer_*() helper calls.
 */
flux_msg_t *flux_recv (flux_t h, struct flux_match match, int flags)
{
    zlist_t *l = NULL;
    flux_msg_t *msg = NULL;
    int saved_errno;

    flags |= h->flags;
    if (!(flags & FLUX_O_NONBLOCK) && (flags & FLUX_O_COPROC) &&
        flux_sleep_on (h, match) < 0) {
        if (errno != EINVAL)
            goto fatal;
        errno = 0;
    }
    do {
        if (!(msg = flux_recv_any (h, flags))) {
            if (errno != EAGAIN && errno != EWOULDBLOCK)
                goto fatal;
            if (defer_requeue (&l, h) < 0)
                goto fatal;
            defer_destroy (&l);
            errno = EWOULDBLOCK;
            return NULL;
        }
        if (!flux_msg_cmp (msg, match)) {
            if (defer_enqueue (&l, msg) < 0)
                goto fatal;
            msg = NULL;
        }
    } while (!msg);
    update_rx_stats (h, msg);
    if ((flags & FLUX_O_TRACE))
        flux_msg_fprint (stderr, msg);
    if (defer_requeue (&l, h) < 0)
        goto fatal;
    defer_destroy (&l);
#if HAVE_CALIPER
    cali_begin_int (h->prof.msg_match_type, match.typemask);
    cali_begin_int (h->prof.msg_match_tag, match.matchtag);
    cali_begin_string (h->prof.msg_match_glob,
                       match.topic_glob ? match.topic_glob : "NONE");
    char *sender = NULL;
    flux_msg_get_route_first (msg, &sender);
    if (sender)
        cali_begin_string (h->prof.msg_sender, sender);
    profiling_msg_snapshot (h, msg, flags, "recv");
    if (sender)
        cali_end (h->prof.msg_sender);
    cali_end (h->prof.msg_match_type);
    cali_end (h->prof.msg_match_tag);
    cali_end (h->prof.msg_match_glob);

    free (sender);
#endif
    return msg;
fatal:
    saved_errno = errno;
    FLUX_FATAL (h);
    if (msg)
        flux_msg_destroy (msg);
    defer_destroy (&l);
    errno = saved_errno;
    return NULL;
}
Ejemplo n.º 6
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);
}