Exemple #1
0
/* Timer pops every 1 ms, writing a new value to key.
 * After 10 calls, it calls kvs_unwatch().
 * After 20 calls, it calls flux_reactor_stop().
 * The kvs_unwatch_cb() counts the number of times it is called, should be 10.
 */
void test_unwatch (int argc, char **argv)
{
    struct timer_ctx ctx;
    flux_reactor_t *r;
    int count = 0;
    flux_watcher_t *timer;

    if (argc != 1) {
        fprintf (stderr, "Usage: unwatch key\n");
        exit (1);
    }
    ctx.key = argv[0];
    if (!(ctx.h = flux_open (NULL, 0)))
        log_err_exit ("flux_open");
    r = flux_get_reactor (ctx.h);
    if (kvs_watch_int (ctx.h, ctx.key, unwatch_watch_cb, &count) < 0)
        log_err_exit ("kvs_watch_int %s", ctx.key);
    if (!(timer = flux_timer_watcher_create (r, 0.001, 0.001,
                                             unwatch_timer_cb, &ctx)))
        log_err_exit ("flux_timer_watcher_create");
    flux_watcher_start (timer);
    if (flux_reactor_run (r, 0) < 0)
        log_err_exit ("flux_reactor_run");
    if (count != 10)
        log_msg_exit ("watch called %d times (should be 10)", count);
    flux_watcher_destroy (timer);
    flux_close (ctx.h);
}
Exemple #2
0
int hello_start (hello_t *hello)
{
    int rc = -1;
    uint32_t rank;

    if (flux_get_rank (hello->h, &rank) < 0)
        goto done;
    if (rank == 0) {
        monotime (&hello->start);
        if (!(hello->timer = flux_timer_watcher_create (hello->reactor,
                                                        hello->timeout,
                                                        hello->timeout,
                                                        timer_cb, hello)))
            goto done;
        flux_watcher_start (hello->timer);
        if (hello_add_rank (hello, 0) < 0)
            goto done;
    } else {
        if (hello_sendmsg (hello, rank) < 0)
            goto done;
    }
    rc = 0;
done:
    return rc;
}
Exemple #3
0
int heartbeat_start (heartbeat_t *hb)
{
    uint32_t rank;
    struct flux_match match = FLUX_MATCH_EVENT;

    if (!hb->h) {
        errno = EINVAL;
        return -1;
    }
    if (flux_get_rank (hb->h, &rank) < 0)
        return -1;
    if (rank == 0) {
        flux_reactor_t *r = flux_get_reactor (hb->h);
        flux_reactor_now_update (r);
        if (!(hb->timer = flux_timer_watcher_create (r, hb->rate, hb->rate,
                                                     timer_cb, hb)))
            return -1;
        flux_watcher_start (hb->timer);
    }
    match.topic_glob = "hb";
    if (!(hb->mh = flux_msg_handler_create (hb->h, match, event_cb, hb)))
        return -1;
    flux_msg_handler_start (hb->mh);
    return 0;
}
Exemple #4
0
static ctx_t *getctx (flux_t *h)
{
    ctx_t *ctx = (ctx_t *)flux_aux_get (h, "flux::barrier");

    if (!ctx) {
        ctx = xzmalloc (sizeof (*ctx));
        if (!(ctx->barriers = zhash_new ())) {
            errno = ENOMEM;
            goto error;
        }
        if (flux_get_rank (h, &ctx->rank) < 0) {
            flux_log_error (h, "flux_get_rank");
            goto error;
        }
        if (!(ctx->timer = flux_timer_watcher_create (flux_get_reactor (h),
                       barrier_reduction_timeout_sec, 0., timeout_cb, ctx) )) {
            flux_log_error (h, "flux_timer_watacher_create");
            goto error;
        }
        ctx->h = h;
        flux_aux_set (h, "flux::barrier", ctx, freectx);
    }
    return ctx;
error:
    freectx (ctx);
    return NULL;
}
Exemple #5
0
static void test_timer (flux_reactor_t *reactor)
{
    flux_watcher_t *w;

    errno = 0;
    ok (!flux_timer_watcher_create (reactor, -1, 0, oneshot, NULL)
        && errno == EINVAL,
        "timer: creating negative timeout fails with EINVAL");
    ok (!flux_timer_watcher_create (reactor, 0, -1, oneshot, NULL)
        && errno == EINVAL,
        "timer: creating negative repeat fails with EINVAL");
    ok ((w = flux_timer_watcher_create (reactor, 0, 0, oneshot, NULL)) != NULL,
        "timer: creating zero timeout works");
    flux_watcher_start (w);
    ok (flux_reactor_run (reactor, 0) == 0,
        "timer: reactor ran to completion (single oneshot)");
    ok (oneshot_ran == true,
        "timer: oneshot was executed");
    oneshot_ran = false;
    ok (flux_reactor_run (reactor, 0) == 0,
        "timer: reactor ran to completion (expired oneshot)");
    ok (oneshot_ran == false,
        "timer: expired oneshot was not re-executed");

    errno = 0;
    oneshot_errno = ESRCH;
    flux_watcher_start (w);
    ok (flux_reactor_run (reactor, 0) < 0 && errno == ESRCH,
        "general: reactor stop_error worked with errno passthru");
    flux_watcher_stop (w);
    flux_watcher_destroy (w);

    ok ((w = flux_timer_watcher_create (reactor, 0.01, 0.01, repeat, NULL))
        != NULL,
        "timer: creating 1ms timeout with 1ms repeat works");
    flux_watcher_start (w);
    ok (flux_reactor_run (reactor, 0) == 0,
        "timer: reactor ran to completion (single repeat)");
    ok (repeat_countdown == 0,
        "timer: repeat timer stopped itself after countdown");
    flux_watcher_stop (w);
    flux_watcher_destroy (w);
}
Exemple #6
0
void *watchthread (void *arg)
{
    thd_t *t = arg;
    watch_count_t wc;
    flux_kvs_txn_t *txn;
    flux_future_t *f;
    flux_reactor_t *r;
    flux_watcher_t *pw = NULL;
    flux_watcher_t *tw = NULL;

    if (!(t->h = flux_open (NULL, 0)))
        log_err_exit ("flux_open");

    /* Make sure key doesn't already exist, initial value may affect
     * test by chance (i.e. initial value = 0, commit 0 and thus no
     * change)
     */
    if (!(txn = flux_kvs_txn_create ()))
        log_err_exit ("flux_kvs_txn_create");
    if (flux_kvs_txn_unlink (txn, 0, key) < 0)
        log_err_exit ("flux_kvs_txn_unlink");
    if (!(f = flux_kvs_commit (t->h, 0, txn)) || flux_future_get (f, NULL) < 0)
        log_err_exit ("flux_kvs_commit");
    flux_future_destroy (f);
    flux_kvs_txn_destroy (txn);

    r = flux_get_reactor (t->h);

    if (flux_kvs_watch (t->h, key, watch_count_cb, t) < 0)
        log_err_exit ("flux_kvs_watch %s", key);

    pw = flux_prepare_watcher_create (r, watch_prepare_cb, NULL);

    wc.t = t;
    wc.lastcount = -1;

    /* So test won't hang if there's a bug */
    tw = flux_timer_watcher_create (r,
                                    WATCH_TIMEOUT,
                                    WATCH_TIMEOUT,
                                    watch_timeout_cb,
                                    &wc);

    flux_watcher_start (pw);
    flux_watcher_start (tw);

    if (flux_reactor_run (r, 0) < 0)
        log_err_exit ("flux_reactor_run");

    flux_watcher_destroy (pw);
    flux_watcher_destroy (tw);
    flux_close (t->h);
    return NULL;
}
Exemple #7
0
static int runlevel_start_subprocess (runlevel_t *r, int level)
{
    flux_subprocess_t *p = NULL;

    assert (r->h != NULL);

    if (r->rc[level].cmd) {
        flux_subprocess_ops_t ops = {
            .on_completion = completion_cb,
            .on_state_change = NULL,
            .on_channel_out = NULL,
            .on_stdout = NULL,
            .on_stderr = NULL,
        };
        flux_reactor_t *reactor = flux_get_reactor (r->h);
        int flags = 0;

        /* set alternate io callback for levels 1 and 3 */
        if (level == 1 || level == 3) {
            ops.on_stdout = io_cb;
            ops.on_stderr = io_cb;
        }
        else
            flags |= FLUX_SUBPROCESS_FLAGS_STDIO_FALLTHROUGH;

        if (!(p = flux_exec (r->h,
                             flags,
                             r->rc[level].cmd,
                             &ops)))
            goto error;

        if (flux_subprocess_aux_set (p, "runlevel", r, NULL) < 0)
            goto error;

        monotime (&r->rc[level].start);
        if (r->rc[level].timeout > 0.) {
            flux_watcher_t *w;
            if (!(w = flux_timer_watcher_create (reactor,
                                                 r->rc[level].timeout, 0.,
                                                 runlevel_timeout, r)))
                goto error;
            flux_watcher_start (w);
            r->rc[level].timer = w;
            flux_log (r->h, LOG_INFO, "runlevel %d (%.1fs) timer started",
                      level, r->rc[level].timeout);
        }

        r->rc[level].p = p;
    } else {
Exemple #8
0
static void event_handler (flux_t *h, flux_msg_handler_t *w,
                           const flux_msg_t *msg, void *arg)
{
    cron_entry_t *e = arg;
    struct cron_event *ev = cron_entry_type_data (e);

    ev->counter++;
    if (ev->paused)
        return;
    /*
     *  Determine if we should run the cron task on this event
     *   based on the current values for "after" and "nth".
     *   If ev->after is set, then only run for the first time
     *   after we've seen this many events. If ev->nth is set,
     *   only run every nth event starting with 'after'.
     */
    if (ev->counter < ev->after)
        return;
    if (ev->nth && ((ev->counter - ev->after) % ev->nth))
        return;
    if (ev->min_interval > 0.) {
        double now = get_timestamp ();
        double remaining = ev->min_interval - (now - e->stats.lastrun);
        if (remaining > 1e-5) {
            flux_reactor_t *r = flux_get_reactor (h);
            flux_watcher_t *w;
            if (!(w = flux_timer_watcher_create (r, remaining, 0.,
                                                 ev_timer_cb, (void *) e)))
                flux_log_error (h, "timer_watcher_create");
            else {
                /* Pause the event watcher. Continue to count events but
                 *  don't run anything until we unpause.
                 */
                ev->paused = 1;
                flux_watcher_start (w);
                flux_log (h, LOG_DEBUG,
                          "cron-%ju: delaying %4.03fs due to min interval",
                          e->id, remaining);
            }
            return;
        }
    }
    cron_entry_schedule_task (e);
}
Exemple #9
0
int shutdown_recvmsg (shutdown_t *s, const flux_msg_t *msg)
{
    int rc = -1;

    if (!s->w) {
        if (shutdown_decode (msg, &s->grace, &s->rc, &s->rank,
                             s->reason, sizeof (s->reason)) < 0)
            goto done;
        if (!(s->w = flux_timer_watcher_create (s->grace, 0., shutdown_cb, s)))
            goto done;
        flux_timer_watcher_start (s->h, s->w);
        if (flux_rank (s->h) == 0)
            flux_log (s->h, LOG_INFO, "%d: shutdown in %.3fs: %s",
                      s->rank, s->grace, s->reason);
    }
    rc = 0;
done:
    return rc;
}
Exemple #10
0
/* On receipt of the shutdown event message, begin the grace timer,
 * and log the "shutdown in..." message on rank 0.
 */
void shutdown_handler (flux_t h, flux_msg_handler_t *w,
                       const flux_msg_t *msg, void *arg)
{
    shutdown_t *s = arg;

    if (!s->timer) {
        if (shutdown_decode (msg, &s->grace, &s->rc, &s->rank,
                             s->reason, sizeof (s->reason)) < 0) {
            flux_log_error (h, "shutdown event");
            return;
        }
        if (!(s->timer = flux_timer_watcher_create (flux_get_reactor (s->h),
                                                    s->grace, 0.,
                                                    timer_handler, s))) {
            flux_log_error (h, "shutdown timer creation");
            return;
        }
        flux_watcher_start (s->timer);
        if (s->myrank == 0)
            flux_log (s->h, LOG_INFO, "shutdown in %.3fs: %s",
                      s->grace, s->reason);
    }
}
Exemple #11
0
int main (int argc, char *argv[])
{
    int ch;
    int pad_bytes = 0;
    char *target;
    flux_watcher_t *tw = NULL;
    struct ping_ctx ctx = {
        .period = 1.0,
        .rank = NULL,
        .nodeid = FLUX_NODEID_ANY,
        .topic = NULL,
        .pad = NULL,
        .count = -1,
        .send_count = 0,
        .batch = false,
    };

    log_init ("flux-ping");

    while ((ch = getopt_long (argc, argv, OPTIONS, longopts, NULL)) != -1) {
        switch (ch) {
            case 'h': /* --help */
                usage ();
                break;
            case 'p': /* --pad bytes */
                pad_bytes = strtoul (optarg, NULL, 10);
                break;
            case 'd': /* --delay seconds */
                ctx.period = strtod (optarg, NULL);
                if (ctx.period < 0)
                    usage ();
                break;
            case 'r': /* --rank NODESET  */
                ctx.rank = optarg;
                break;
            case 'c': /* --count N */
                ctx.count = strtoul (optarg, NULL, 10);
                break;
            case 'b': /* --batch-request */
                ctx.batch = true;
                break;
            default:
                usage ();
                break;
        }
    }
    if (optind != argc - 1)
        usage ();
    if (ctx.batch && ctx.count == -1)
        log_msg_exit ("--batch should only be used with --count");
    target = argv[optind++];

    /* Create null terminated pad string for reuse in each message.
     * By default it's the empty string.
     */
    ctx.pad = xzmalloc (pad_bytes + 1);
    memset (ctx.pad, 'p', pad_bytes);

    /* If "rank!" is prepended to the target, and there is no --rank
     * argument, snip it off and set the rank.  If it's just the bare
     * rank, assume the target is "cmb".
     */
    if (ctx.rank == NULL) {
        char *p;
        nodeset_t *ns = NULL;
        if ((p = strchr (target, '!'))) {
            *p++ = '\0';
            ctx.rank = target;
            target = p;
        } else if ((ns = nodeset_create_string (target)) != NULL) {
            ctx.rank = target;
            target = "cmb";
            nodeset_destroy (ns);
        } else if (!strcmp (target, "all")) {
            ctx.rank = target;
            target = "cmb";
        }
    }
    /* Use singleton rpc if there's only one nodeid
     */
    if (ctx.rank != NULL) {
        nodeset_t *ns = nodeset_create_string (ctx.rank);
        if (ns) {
            if (nodeset_count (ns) == 1) {
                ctx.nodeid = nodeset_min (ns);
                ctx.rank = NULL;
            }
            nodeset_destroy (ns);
        }
    }

    ctx.topic = xasprintf ("%s.ping", target);

    if (!(ctx.h = flux_open (NULL, 0)))
        log_err_exit ("flux_open");
    if (!(ctx.reactor = flux_get_reactor (ctx.h)))
        log_err_exit ("flux_get_reactor");

    /* In batch mode, requests are sent before reactor is started
     * to process responses.  o/w requests are set in a timer watcher.
     */
    if (ctx.batch) {
        while (ctx.send_count < ctx.count) {
            send_ping (&ctx);
            usleep ((useconds_t)(ctx.period * 1E6));
        }
    } else {
        tw = flux_timer_watcher_create (ctx.reactor, ctx.period, ctx.period,
                                        timer_cb, &ctx);
        if (!tw)
            log_err_exit ("error creating watchers");
        flux_watcher_start (tw);
    }
    if (flux_reactor_run (ctx.reactor, 0) < 0)
        log_err_exit ("flux_reactor_run");

    /* Clean up.
     */
    flux_watcher_destroy (tw);

    free (ctx.topic);
    free (ctx.pad);

    flux_close (ctx.h);
    log_fini ();

    return 0;
}