int main (int argc, char *argv[]) { nodeset_t *n, *n2; nodeset_iterator_t *itr; int i; struct timespec ts; uint32_t bigset = 1E6; char *tmp; plan (NO_PLAN); n = nodeset_create (); ok (n != NULL); nodeset_config_brackets (n, false); /* obtain constants used in other tests */ uint32_t maxrank = nodeset_getattr (n, NODESET_ATTR_MAXRANK); uint32_t minsize = nodeset_getattr (n, NODESET_ATTR_MINSIZE); uint32_t maxsize = nodeset_getattr (n, NODESET_ATTR_MAXSIZE); nodeset_add_rank (n, 8); nodeset_add_rank (n, 7); nodeset_add_rank (n, 9); like (nodeset_string (n), "7-9", "consecutive adds become range"); ok (nodeset_count (n) == 3); nodeset_add_rank (n, 1); like (nodeset_string (n), "1,7-9", "singleton prepended to range"); ok (nodeset_count (n) == 4); nodeset_add_rank (n, 16); like (nodeset_string (n), "1,7-9,16", "singleton appended to range"); ok (nodeset_count (n) == 5); nodeset_add_rank (n, 14); like (nodeset_string (n), "1,7-9,14,16", "singleton embedded in range"); ok (nodeset_count (n) == 6); nodeset_add_rank (n, 3); like (nodeset_string (n), "1,3,7-9,14,16", "singleton embedded in range 2"); ok (nodeset_count (n) == 7); nodeset_add_range (n, 1, 3); like (nodeset_string (n), "1-3,7-9,14,16", "overlapping range"); ok (nodeset_count (n) == 8); nodeset_add_range (n, 5, 8); like (nodeset_string (n), "1-3,5-9,14,16", "overlapping range 2"); ok (nodeset_count (n) == 10); nodeset_add_range (n, 8, 11); like (nodeset_string (n), "1-3,5-11,14,16", "overlapping range 3"); ok (nodeset_count (n) == 12); nodeset_add_range (n, 1, 16); like (nodeset_string (n), "1-16", "add range that contains existing"); ok (nodeset_count (n) == 16); nodeset_add_range (n, 4, 8); like (nodeset_string (n), "1-16", "add range contained by existing"); ok (nodeset_count (n) == 16); nodeset_destroy (n); /********************************************/ n = nodeset_create (); ok (n != NULL); nodeset_add_rank (n, 0); nodeset_add_rank (n, 1); nodeset_add_rank (n, 2); like (nodeset_string (n), "\\[0-2\\]", "edge case 1 merges with 0"); ok (nodeset_count (n) == 3); nodeset_config_ranges (n, false); like (nodeset_string (n), "\\[0,1,2\\]"); nodeset_destroy (n); /********************************************/ n = nodeset_create (); ok (n != NULL); nodeset_add_rank (n, 2); nodeset_add_rank (n, 1); nodeset_add_rank (n, 0); like (nodeset_string (n), "\\[0-2\\]", "reverse merge works"); ok (nodeset_count (n) == 3); nodeset_destroy (n); /********************************************/ n = nodeset_create_string ("[1,3,5,6-100]"); ok (n != NULL); like (nodeset_string (n), "\\[1,3,5-100\\]", "mundane range string works"); ok (nodeset_count (n) == 98); nodeset_destroy (n); n = nodeset_create_string ("2-1"); ok (n != NULL); like (nodeset_string (n), "\\[1-2\\]", "numerically reversed range handled"); ok (nodeset_count (n) == 2); nodeset_destroy (n); n = nodeset_create_string (""); ok (n != NULL); ok (nodeset_count (n) == 0); like (nodeset_string (n), "", "empty string produces empty range"); nodeset_destroy (n); n = nodeset_create_string (","); ok (n == NULL, "comma by itself produces error"); n = nodeset_create_string ("-1"); ok (n == NULL, "range missing start produces error"); n = nodeset_create_string ("1-"); ok (n == NULL, "range missing end produces error"); n = nodeset_create_string ("foo1"); ok (n == NULL, "alpha with numerical suffix produces error"); n = nodeset_create_string ("[1-2]"); ok (n != NULL); like (nodeset_string (n), "\\[1-2\\]", "bracketed range works"); ok (nodeset_count (n) == 2); nodeset_destroy (n); n = nodeset_create_string ("xyz"); ok (n == NULL, "alpha by itself produces error"); /********************************************/ n = nodeset_create_string ("0-2"); ok (n != NULL); ok (nodeset_test_rank (n, 0)); ok (nodeset_test_rank (n, 1)); ok (nodeset_test_rank (n, 2)); ok (!nodeset_test_rank (n, 3)); ok (!nodeset_test_rank (n, nodeset_getattr (n, NODESET_ATTR_SIZE) - 1), "nodeset_test_rank (internal size - 1) fails"); ok (!nodeset_test_rank (n, nodeset_getattr (n, NODESET_ATTR_SIZE)), "nodeset_test_rank (internal size) fails"); ok (!nodeset_test_rank (n, nodeset_getattr (n, NODESET_ATTR_SIZE) + 1), "nodeset_test_rank (internal size + 1) fails"); ok (!nodeset_test_range (n, 2, nodeset_getattr (n, NODESET_ATTR_SIZE) - 1), "nodeset_test_range (2, internal size - 1) fails"); ok (!nodeset_test_range (n, 2, nodeset_getattr (n, NODESET_ATTR_SIZE)), "nodeset_test_range (2, internal size) fails"); ok (!nodeset_test_range (n, 2, nodeset_getattr (n, NODESET_ATTR_SIZE) + 1), "nodeset_test_range (2, internal size + 1) fails"); ok (!nodeset_test_range (n, nodeset_getattr (n, NODESET_ATTR_SIZE) - 1, 2), "nodeset_test_range (internal size - 1, 2) fails"); ok (!nodeset_test_range (n, nodeset_getattr (n, NODESET_ATTR_SIZE), 2), "nodeset_test_range (internal size, 2) fails"); ok (!nodeset_test_range (n, nodeset_getattr (n, NODESET_ATTR_SIZE) + 1, 2), "nodeset_test_range (internal size + 1, 2) fails"); nodeset_config_brackets (n, false); like (nodeset_string (n), "0-2"); ok (nodeset_test_range (n, 0, 2), "nodeset_test_range works"); nodeset_delete_rank (n, 0); like (nodeset_string (n), "1-2", "nodeset_delete_rank works"); ok (!nodeset_test_rank (n, 0), "nodeset_test_rank works"); ok (nodeset_test_range (n, 1, 2)); nodeset_delete_rank (n, 1); ok (!nodeset_test_rank (n, 0)); ok (!nodeset_test_rank (n, 1)); ok (nodeset_test_rank (n, 2)); ok (!strcmp (nodeset_string (n), "2")); nodeset_delete_rank (n, 2); ok (!nodeset_test_rank (n, 0)); ok (!nodeset_test_rank (n, 1)); ok (!nodeset_test_rank (n, 2)); like (nodeset_string (n), ""); nodeset_destroy (n); /********************************************/ /* Exercise iteration */ n = nodeset_create_string ("0-2"); ok (n != NULL); itr = nodeset_iterator_create (n); ok (nodeset_next (itr) == 0, "iterator_next works on first element"); ok (nodeset_next (itr) == 1, "iterator_next works on next element"); ok (nodeset_next (itr) == 2, "iterator_next works on last element"); ok (nodeset_next (itr) == NODESET_EOF, "iterator_next returns EOF"); nodeset_iterator_rewind (itr); ok (nodeset_next (itr) == 0, "iterator rewind works"); nodeset_iterator_destroy (itr); nodeset_destroy (n); /********************************************/ /* Exercise iteration with nodeset_next_rank */ n = nodeset_create_string ("0,2-3,7"); ok (n != NULL); int r = nodeset_min (n); ok (r == 0, "nodeset_min"); ok ((r = nodeset_next_rank (n, r)) == 2, "nodeset_next_rank (n, min) returns second element"); ok ((r = nodeset_next_rank (n, r)) == 3, "nodeset_next_rank works on third element"); ok ((r = nodeset_next_rank (n, r)) == 7, "nodeset_next_rank works on fourth element"); ok ((r = nodeset_next_rank (n, r)) == NODESET_EOF, "nodeset_next_rank detects end of nodeset"); ok ((r = nodeset_next_rank (n, 1)) == 2, "nodeset_next_rank returns next rank even if arg not in set"); /********************************************/ /* Exercise nodeset_dup */ n = nodeset_create_string ("0-2"); ok (n != NULL); nodeset_config_brackets (n, false); like (nodeset_string (n), "0-2"); n2 = nodeset_dup (n); ok (n2 != NULL, "nodeset_dup says it worked"); like (nodeset_string (n2), "0-2", "nodeset_dup returned identical nodeset"); nodeset_add_rank (n, 4); nodeset_add_rank (n2, 5); like (nodeset_string (n), "0-2,4", "orig unaffected by changes in dup"); like (nodeset_string (n2), "0-2,5", "dup unaffected by changes in orig"); nodeset_destroy (n); nodeset_destroy (n2); /********************************************/ /* Try zero padding. */ n = nodeset_create_string ("[1,3,5,6-100]"); ok (n != NULL); nodeset_config_brackets (n, false); like (nodeset_string (n), "1,3,5-100", "results not zero padded by default"); //nodeset_config_padding (n, log10 (nodeset_max (n)) + 1); nodeset_config_padding (n, 3); like (nodeset_string (n), "001,003,005-100", "padding 3 on all all works"); nodeset_config_padding (n, 2); like (nodeset_string (n), "01,03,05-100", "padding 2 on subset works"); nodeset_config_padding (n, 4); like (nodeset_string (n), "0001,0003,0005-0100", "padding 4 on all works"); nodeset_destroy (n); /********************************************/ /* Add 'bigset' consecutive singletons. */ n = nodeset_create (); ok (n != NULL); nodeset_config_brackets (n, false); ok (nodeset_resize (n, bigset), "explicitly resize to %u", bigset); monotime (&ts); for (i = 0; i < bigset; i++) if (!nodeset_add_rank (n, i)) break; ok (i == bigset, "added %u consecutive ranks [%.2fs %u Mbytes]", bigset, monotime_since (ts)/1000, nodeset_getattr (n, NODESET_ATTR_BYTES)/1024); monotime (&ts); tmp = xasprintf ("0-%u", bigset - 1); like (nodeset_string (n), tmp, "string conversion %s [%.2fs %u Mbytes]", tmp, monotime_since (ts)/1000, nodeset_getattr (n, NODESET_ATTR_BYTES)/1024); free (tmp); ok (nodeset_count (n) == bigset, "large nodeset count is sane"); nodeset_destroy (n); /********************************************/ /* Add 'bigset'/2 non-consecutive singletons. */ n = nodeset_create (); ok (n != NULL); nodeset_config_brackets (n, false); ok (nodeset_resize (n, bigset), "explicitly resize to %u", bigset); monotime (&ts); for (i = 0; i < bigset; i += 2) if (!nodeset_add_rank (n, i)) break; ok (i == bigset, "added %u non-consecutive ranks [%.2fs %u Mbytes]", bigset/2, monotime_since (ts)/1000, nodeset_getattr (n, NODESET_ATTR_BYTES)/1024); monotime (&ts); ok (nodeset_string (n) != NULL, "string conversion [%.2fs %u Mbytes]", monotime_since (ts)/1000, nodeset_getattr (n, NODESET_ATTR_BYTES)/1024); ok (nodeset_count (n) == bigset/2, "large nodeset count is sane"); nodeset_destroy (n); /********************************************/ /* Check edge cases with very big ranks and resize. */ bool skip_huge = true; n = nodeset_create (); nodeset_config_brackets (n, false); ok (nodeset_getattr (n, NODESET_ATTR_SIZE) == minsize, "veb size is the minimum %u", minsize); monotime (&ts); ok (!nodeset_add_rank (n, maxrank + 1), "adding max+1 %u rank fails [%.2fs %u Mbytes]", maxrank + 1, monotime_since (ts)/1000, nodeset_getattr (n, NODESET_ATTR_BYTES)/(1024*1024)); ok (nodeset_getattr (n, NODESET_ATTR_SIZE) == minsize, "veb size is the minimum %u", minsize); skip (skip_huge, 16, "too slow"); monotime (&ts); ok (nodeset_add_rank (n, maxrank), "add max rank %u [%.2fs %u Mbytes]", maxrank, monotime_since (ts)/1000, nodeset_getattr (n, NODESET_ATTR_BYTES)/(1024*1024)); ok (nodeset_getattr (n, NODESET_ATTR_SIZE) == maxsize, "veb size is the maximum %u", maxsize); /* 2 */ monotime (&ts); ok (nodeset_add_rank (n, maxrank - 1), "add max-1 %u [%.2fs %u Mbytes]", maxrank - 1, monotime_since (ts)/1000, nodeset_getattr (n, NODESET_ATTR_BYTES)/(1024*1024)); ok (nodeset_test_rank (n, maxrank - 1), "test rank max - 1"); ok (nodeset_test_rank (n, maxrank), "test rank max"); ok (!nodeset_test_rank (n, maxrank + 1), "test rank max + 1"); ok (nodeset_count (n) == 2, "nodeset count is sane"); /* 7 */ tmp = xasprintf ("%u-%u", maxrank-1, maxrank); monotime (&ts); like (nodeset_string (n), tmp, "convert to string %s [%.2fs %u Mbytes]", tmp, monotime_since (ts)/1000, nodeset_getattr (n, NODESET_ATTR_BYTES)/(1024*1024)); free (tmp); /* 8 */ ok (nodeset_resize (n, 0), "resize to 0 returns success"); ok (nodeset_getattr (n, NODESET_ATTR_SIZE) == maxsize, "nodeset size remains max %u", maxsize); /* 10 */ nodeset_delete_rank (n, maxrank - 1); ok (!nodeset_test_rank (n, maxrank - 1), "nodeset_del max - 1 works"); ok (nodeset_test_rank (n, maxrank)); ok (!nodeset_test_rank (n, maxrank + 1)); /* 13 */ nodeset_delete_rank (n, maxrank + 1); ok (!nodeset_test_rank (n, maxrank - 1), "nodeset_del max + 1 has no effect"); ok (nodeset_test_rank (n, maxrank)); ok (!nodeset_test_rank (n, maxrank + 1)); /* 16 */ end_skip; nodeset_delete_rank (n, maxrank); ok (!nodeset_test_rank (n, maxrank - 1), "nodeset_del max works"); ok (!nodeset_test_rank (n, maxrank)); ok (!nodeset_test_rank (n, maxrank + 1)); /* 19 */ ok (nodeset_resize (n, 0), "resize to zero returns success"); ok (nodeset_getattr (n, NODESET_ATTR_SIZE) == minsize, "nodeset size is the minimum %u", minsize); nodeset_destroy (n); done_testing (); }
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; }