This source file includes following definitions.
- pmix_test_output_prepare
- parse_cmd
- fcon
- fdes
- parse_token
- parse_fence
- parse_noise
- is_digit
- parse_replace
- get_total_ns_number
- get_all_ranks_from_namespace
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #include <src/include/pmix_config.h>
16 #include <pmix_common.h>
17
18 #include "test_common.h"
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <ctype.h>
22
23 int pmix_test_verbose = 0;
24
25 FILE *file;
26
27 #define OUTPUT_MAX 1024
28 char *pmix_test_output_prepare(const char *fmt, ... )
29 {
30 static char output[OUTPUT_MAX];
31 va_list args;
32 va_start( args, fmt );
33 memset(output, 0, sizeof(output));
34 vsnprintf(output, OUTPUT_MAX - 1, fmt, args);
35 va_end(args);
36 return output;
37 }
38
39 void parse_cmd(int argc, char **argv, test_params *params)
40 {
41 int i;
42
43
44 file = stdout;
45 if( params->nspace != NULL ) {
46 params->nspace = NULL;
47 }
48
49
50 for (i=1; i < argc; i++) {
51 if (0 == strcmp(argv[i], "--n") || 0 == strcmp(argv[i], "-n")) {
52 i++;
53 if (NULL != argv[i]) {
54 params->np = strdup(argv[i]);
55 params->nprocs = strtol(argv[i], NULL, 10);
56 if (-1 == params->ns_size) {
57 params->ns_size = params->nprocs;
58 }
59 }
60 } else if (0 == strcmp(argv[i], "--h") || 0 == strcmp(argv[i], "-h")) {
61
62 fprintf(stderr, "usage: pmix_test [-h] [-e foo] [-b] [-c] [-nb]\n");
63 fprintf(stderr, "\t-n provides information about the job size (for checking purposes)\n");
64 fprintf(stderr, "\t-e foo use foo as test client\n");
65 fprintf(stderr, "\t-v verbose output\n");
66 fprintf(stderr, "\t-t <> set timeout\n");
67 fprintf(stderr, "\t-o out redirect clients logs to file out.<rank>\n");
68 fprintf(stderr, "\t--early-fail force client process with rank 0 to fail before PMIX_Init.\n");
69 fprintf(stderr, "\t--ns-dist n1:n2:n3 register n namespaces (3 in this example) each with ni ranks (n1, n2 or n3).\n");
70 fprintf(stderr, "\t--fence \"[<data_exchange><blocking> | ns0:ranks;ns1:ranks...][...]\" specify fences in different configurations.\n");
71 fprintf(stderr, "\t--use-same-keys relative to the --fence option: put the same keys in the interim between multiple fences.\n");
72 fprintf(stderr, "\t--job-fence test fence inside its own namespace.\n");
73 fprintf(stderr, "\t-c relative to the --job-fence option: fence[_nb] callback shall include all collected data\n");
74 fprintf(stderr, "\t-nb relative to the --job-fence option: use non-blocking fence\n");
75 fprintf(stderr, "\t--noise \"[ns0:ranks;ns1:ranks...]\" add system noise to specified processes.\n");
76 fprintf(stderr, "\t--test-publish test publish/lookup/unpublish api.\n");
77 fprintf(stderr, "\t--test-spawn test spawn api.\n");
78 fprintf(stderr, "\t--test-connect test connect/disconnect api.\n");
79 fprintf(stderr, "\t--test-resolve-peers test resolve_peers api.\n");
80 fprintf(stderr, "\t--test-error test error handling api.\n");
81 fprintf(stderr, "\t--test-replace N:k0,k1,...,k(N-1) test key replace for N keys, k0,k1,k(N-1) - key indexes to replace \n");
82 fprintf(stderr, "\t--test-internal N test store internal key, N - number of internal keys\n");
83 fprintf(stderr, "\t--gds <external gds name> set GDS module \"--gds hash|ds12\", default is hash\n");
84 exit(0);
85 } else if (0 == strcmp(argv[i], "--exec") || 0 == strcmp(argv[i], "-e")) {
86 i++;
87 if (NULL != argv[i]) {
88 params->binary = strdup(argv[i]);
89 }
90 } else if (0 == strcmp(argv[i], "--nservers") || 0 == strcmp(argv[i], "-s")){
91 i++;
92 if (NULL != argv[i]) {
93 params->nservers = atoi(argv[i]);
94 }
95 } else if( 0 == strcmp(argv[i], "--verbose") || 0 == strcmp(argv[i],"-v") ){
96 TEST_VERBOSE_ON();
97 params->verbose = 1;
98 } else if (0 == strcmp(argv[i], "--timeout") || 0 == strcmp(argv[i], "-t")) {
99 i++;
100 if (NULL != argv[i]) {
101 params->timeout = atoi(argv[i]);
102 if( params->timeout == 0 ){
103 params->timeout = TEST_DEFAULT_TIMEOUT;
104 }
105 }
106 } else if( 0 == strcmp(argv[i], "-o")) {
107 i++;
108 if (NULL != argv[i]) {
109 params->prefix = strdup(argv[i]);
110 }
111 } else if( 0 == strcmp(argv[i], "-s")) {
112 i++;
113 if (NULL != argv[i]) {
114 params->nspace = strdup(argv[i]);
115 }
116 } else if (0 == strcmp(argv[i], "--rank") || 0 == strcmp(argv[i], "-r")) {
117 i++;
118 if (NULL != argv[i]) {
119 params->rank = strtol(argv[i], NULL, 10);
120 }
121 } else if( 0 == strcmp(argv[i], "--early-fail") ){
122 params->early_fail = 1;
123 } else if (0 == strcmp(argv[i], "--fence")) {
124 i++;
125 if (NULL != argv[i]) {
126 params->fences = strdup(argv[i]);
127 if (0 != parse_fence(params->fences, 0)) {
128 fprintf(stderr, "Incorrect --fence option format: %s\n", params->fences);
129 exit(1);
130 }
131 }
132 } else if (0 == strcmp(argv[i], "--use-same-keys")) {
133 params->use_same_keys = 1;
134 } else if (0 == strcmp(argv[i], "--job-fence")) {
135 params->test_job_fence = 1;
136 } else if (0 == strcmp(argv[i], "--collect-corrupt")) {
137 params->collect_bad = 1;
138 } else if (0 == strcmp(argv[i], "--collect") || 0 == strcmp(argv[i], "-c")) {
139 params->collect = 1;
140 } else if (0 == strcmp(argv[i], "--non-blocking") || 0 == strcmp(argv[i], "-nb")) {
141 params->nonblocking = 1;
142 } else if (0 == strcmp(argv[i], "--noise")) {
143 i++;
144 if (NULL != argv[i]) {
145 params->noise = strdup(argv[i]);
146 if (0 != parse_noise(params->noise, 0)) {
147 fprintf(stderr, "Incorrect --noise option format: %s\n", params->noise);
148 exit(1);
149 }
150 }
151 } else if (0 == strcmp(argv[i], "--ns-dist")) {
152 i++;
153 if (NULL != argv[i]) {
154 params->ns_dist = strdup(argv[i]);
155 }
156 } else if (0 == strcmp(argv[i], "--ns-size")) {
157 i++;
158 if (NULL != argv[i]) {
159 params->ns_size = strtol(argv[i], NULL, 10);
160 }
161 } else if (0 == strcmp(argv[i], "--ns-id")) {
162 i++;
163 if (NULL != argv[i]) {
164 params->ns_id = strtol(argv[i], NULL, 10);
165 }
166 } else if (0 == strcmp(argv[i], "--base-rank")) {
167 i++;
168 if (NULL != argv[i]) {
169 params->base_rank = strtol(argv[i], NULL, 10);
170 }
171 } else if( 0 == strcmp(argv[i], "--test-publish") ){
172 params->test_publish = 1;
173 } else if( 0 == strcmp(argv[i], "--test-spawn") ){
174 params->test_spawn = 1;
175 } else if( 0 == strcmp(argv[i], "--test-connect") ){
176 params->test_connect = 1;
177 } else if( 0 == strcmp(argv[i], "--test-resolve-peers") ){
178 params->test_resolve_peers = 1;
179 } else if( 0 == strcmp(argv[i], "--test-error") ){
180 params->test_error = 1;
181 } else if(0 == strcmp(argv[i], "--test-replace") ) {
182 i++;
183 if (NULL != argv[i] && (*argv[i] != '-')) {
184 params->key_replace = strdup(argv[i]);
185 if (0 != parse_replace(params->key_replace, 0, NULL)) {
186 fprintf(stderr, "Incorrect --test-replace option format: %s\n", params->key_replace);
187 exit(1);
188 }
189 } else {
190 params->key_replace = strdup(TEST_REPLACE_DEFAULT);
191 }
192 } else if(0 == strcmp(argv[i], "--test-internal")) {
193 i++;
194 if ((NULL != argv[i]) && (*argv[i] != '-')) {
195 params->test_internal = strtol(argv[i], NULL, 10);
196 } else {
197 params->test_internal = 1;
198 }
199 } else if(0 == strcmp(argv[i], "--gds") ) {
200 i++;
201 params->gds_mode = strdup(argv[i]);
202 }
203
204 else {
205 fprintf(stderr, "unrecognized option: %s\n", argv[i]);
206 exit(1);
207 }
208 }
209 if (NULL == params->binary) {
210 char *basename = NULL;
211 basename = strrchr(argv[0], '/');
212 if (basename) {
213 *basename = '\0';
214
215
216
217
218
219
220
221
222
223
224
225
226 if (0 > asprintf(¶ms->binary, "%s/../pmix_client", argv[0])) {
227 exit(1);
228 }
229 *basename = '/';
230 } else {
231 if (0 > asprintf(¶ms->binary, "pmix_client")) {
232 exit(1);
233 }
234 }
235 }
236
237 if( params->collect_bad ){
238 params->collect = params->rank % 2;
239 }
240
241
242 if( PMIX_RANK_UNDEF == params->rank ){
243 char *ranklist = getenv("SLURM_GTIDS");
244 char *rankno = getenv("SLURM_LOCALID");
245 if( NULL != ranklist && NULL != rankno ){
246 char **argv = pmix_argv_split(ranklist, ',');
247 int count = pmix_argv_count(argv);
248 int rankidx = strtoul(rankno, NULL, 10);
249 if( rankidx >= count ){
250 fprintf(stderr, "It feels like we are running under SLURM:\n\t"
251 "SLURM_GTIDS=%s, SLURM_LOCALID=%s\nbut env vars are conflicting\n",
252 ranklist, rankno);
253 exit(1);
254 }
255 params->rank = strtoul(argv[rankidx], NULL, 10);
256 pmix_argv_free(argv);
257 }
258 }
259
260
261 if( NULL == params->nspace ){
262 char *nspace = getenv("PMIX_NAMESPACE");
263 if( NULL != nspace ){
264 params->nspace = strdup(nspace);
265 }
266 }
267 }
268
269 static void fcon(fence_desc_t *p)
270 {
271 p->blocking = 0;
272 p->data_exchange = 0;
273 p->participants = PMIX_NEW(pmix_list_t);
274 }
275
276 static void fdes(fence_desc_t *p)
277 {
278 PMIX_LIST_RELEASE(p->participants);
279 }
280
281 PMIX_CLASS_INSTANCE(fence_desc_t,
282 pmix_list_item_t,
283 fcon, fdes);
284
285 PMIX_CLASS_INSTANCE(participant_t,
286 pmix_list_item_t,
287 NULL, NULL);
288
289 PMIX_CLASS_INSTANCE(key_replace_t,
290 pmix_list_item_t,
291 NULL, NULL);
292
293 static int ns_id = -1;
294 static fence_desc_t *fdesc = NULL;
295 pmix_list_t *participants = NULL;
296 pmix_list_t test_fences;
297 pmix_list_t *noise_range = NULL;
298 pmix_list_t key_replace;
299
300 #define CHECK_STRTOL_VAL(val, str, store) do { \
301 if (0 == val) { \
302 if (0 != strncmp(str, "0", 1)) { \
303 if (!store) { \
304 return 1; \
305 } \
306 } \
307 } \
308 } while (0)
309
310 static int parse_token(char *str, int step, int store)
311 {
312 char *pch;
313 int count = 0;
314 int remember = -1;
315 int i;
316 int rank;
317 participant_t *proc;
318
319 switch (step) {
320 case 0:
321 if (store) {
322 fdesc = PMIX_NEW(fence_desc_t);
323 participants = fdesc->participants;
324 }
325 pch = strchr(str, '|');
326 if (NULL != pch) {
327 while (pch != str) {
328 if ('d' == *str) {
329 if (store && NULL != fdesc) {
330 fdesc->data_exchange = 1;
331 }
332 } else if ('b' == *str) {
333 if (store && NULL != fdesc) {
334 fdesc->blocking = 1;
335 }
336 } else if (' ' != *str) {
337 if (!store) {
338 return 1;
339 }
340 }
341 str++;
342 }
343 if (0 < parse_token(pch+1, 1, store)) {
344 if (!store) {
345 return 1;
346 }
347 }
348 } else {
349 if (0 < parse_token(str, 1, store)) {
350 if (!store) {
351 return 1;
352 }
353 }
354 }
355 if (store && NULL != fdesc) {
356 pmix_list_append(&test_fences, &fdesc->super);
357 }
358 break;
359 case 1:
360 if (store && NULL == participants) {
361 participants = PMIX_NEW(pmix_list_t);
362 noise_range = participants;
363 }
364 pch = strtok(str, ";");
365 while (NULL != pch) {
366 if (0 < parse_token(pch, 2, store)) {
367 if (!store) {
368 return 1;
369 }
370 }
371 pch = strtok (NULL, ";");
372 }
373 break;
374 case 2:
375 pch = strchr(str, ':');
376 if (NULL != pch) {
377 *pch = '\0';
378 pch++;
379 while (' ' == *str) {
380 str++;
381 }
382 ns_id = (int)(strtol(str, NULL, 10));
383 CHECK_STRTOL_VAL(ns_id, str, store);
384 if (0 < parse_token(pch, 3, store)) {
385 if (!store) {
386 return 1;
387 }
388 }
389 } else {
390 if (!store) {
391 return 1;
392 }
393 }
394 break;
395 case 3:
396 while (' ' == *str) {
397 str++;
398 }
399 if ('\0' == *str) {
400
401 if (store && NULL != participants) {
402 proc = PMIX_NEW(participant_t);
403 (void)snprintf(proc->proc.nspace, PMIX_MAX_NSLEN, "%s-%d", TEST_NAMESPACE, ns_id);
404 proc->proc.rank = PMIX_RANK_WILDCARD;
405 pmix_list_append(participants, &proc->super);
406 }
407 }
408 while ('\0' != *str) {
409 if (',' == *str && 0 != count) {
410 *str = '\0';
411 if (-1 != remember) {
412 rank = (int)(strtol(str-count, NULL, 10));
413 CHECK_STRTOL_VAL(rank, str-count, store);
414 for (i = remember; i < rank; i++) {
415 if (store && NULL != participants) {
416 proc = PMIX_NEW(participant_t);
417 (void)snprintf(proc->proc.nspace, PMIX_MAX_NSLEN, "%s-%d", TEST_NAMESPACE, ns_id);
418 proc->proc.rank = i;
419 pmix_list_append(participants, &proc->super);
420 }
421 }
422 remember = -1;
423 }
424 rank = (int)(strtol(str-count, NULL, 10));
425 CHECK_STRTOL_VAL(rank, str-count, store);
426 if (store && NULL != participants) {
427 proc = PMIX_NEW(participant_t);
428 (void)snprintf(proc->proc.nspace, PMIX_MAX_NSLEN, "%s-%d", TEST_NAMESPACE, ns_id);
429 proc->proc.rank = rank;
430 pmix_list_append(participants, &proc->super);
431 }
432 count = -1;
433 } else if ('-' == *str && 0 != count) {
434 *str = '\0';
435 remember = (int)(strtol(str-count, NULL, 10));
436 CHECK_STRTOL_VAL(remember, str-count, store);
437 count = -1;
438 }
439 str++;
440 count++;
441 }
442 if (0 != count) {
443 if (-1 != remember) {
444 rank = (int)(strtol(str-count, NULL, 10));
445 CHECK_STRTOL_VAL(rank, str-count, store);
446 for (i = remember; i < rank; i++) {
447 if (store && NULL != participants) {
448 proc = PMIX_NEW(participant_t);
449 (void)snprintf(proc->proc.nspace, PMIX_MAX_NSLEN, "%s-%d", TEST_NAMESPACE, ns_id);
450 proc->proc.rank = i;
451 pmix_list_append(participants, &proc->super);
452 }
453 }
454 remember = -1;
455 }
456 rank = (int)(strtol(str-count, NULL, 10));
457 CHECK_STRTOL_VAL(rank, str-count, store);
458 if (store && NULL != participants) {
459 proc = PMIX_NEW(participant_t);
460 (void)snprintf(proc->proc.nspace, PMIX_MAX_NSLEN, "%s-%d", TEST_NAMESPACE, ns_id);
461 proc->proc.rank = rank;
462 pmix_list_append(participants, &proc->super);
463 }
464 }
465 break;
466 default:
467 fprintf(stderr, "Incorrect parsing step.\n");
468 return 1;
469 }
470 return 0;
471 }
472
473 int parse_fence(char *fence_param, int store)
474 {
475 int ret = 0;
476 char *tmp = strdup(fence_param);
477 char * pch, *ech;
478
479 pch = strchr(tmp, '[');
480 while (NULL != pch) {
481 pch++;
482 ech = strchr(pch, ']');
483 if (NULL != ech) {
484 *ech = '\0';
485 ech++;
486 ret += parse_token(pch, 0, store);
487 pch = strchr(ech, '[');
488 } else {
489 ret = 1;
490 break;
491 }
492 }
493 free(tmp);
494 return ret;
495 }
496
497 int parse_noise(char *noise_param, int store)
498 {
499 int ret = 0;
500 char *tmp = strdup(noise_param);
501 char * pch, *ech;
502
503 pch = strchr(tmp, '[');
504 if (NULL != pch) {
505 pch++;
506 ech = strchr(pch, ']');
507 if (NULL != ech) {
508 *ech = '\0';
509 ech++;
510 if ('\0' != *ech) {
511 ret = 1;
512 } else {
513 ret = parse_token(pch, 1, store);
514 }
515 } else {
516 ret = 1;
517 }
518 }
519 free(tmp);
520 return ret;
521 }
522
523 static int is_digit(const char *str)
524 {
525 if (NULL == str)
526 return 0;
527
528 while (0 != *str) {
529 if (!isdigit(*str)) {
530 return 0;
531 }
532 else {
533 str++;
534 }
535 }
536 return 1;
537 }
538
539 int parse_replace(char *replace_param, int store, int *key_num) {
540 int ret = 0;
541 char *tmp = strdup(replace_param);
542 char tmp_str[32];
543 char * pch, *ech;
544 key_replace_t *item;
545 int cnt = 0;
546
547 if (NULL == replace_param) {
548 free(tmp);
549 return 1;
550 }
551
552 pch = strchr(tmp, ':');
553 snprintf(tmp_str, pch - tmp + 1, "%s", tmp);
554 cnt = atol(tmp_str);
555
556 if (NULL != key_num) {
557 *key_num = cnt;
558 }
559
560 while(NULL != pch) {
561 pch++;
562 ech = strchr(pch, ',');
563 if (strlen(pch) > 0) {
564 if (NULL != ech) {
565 snprintf(tmp_str, ech - pch + 1, "%s", pch);
566 } else {
567 snprintf(tmp_str, strlen(pch) + 1, "%s", pch);
568 }
569 if ((0 == is_digit(tmp_str)) || ((atoi(tmp_str) + 1) > cnt)) {
570 ret = 1;
571 break;
572 }
573 pch = ech;
574 if (store) {
575 item = PMIX_NEW(key_replace_t);
576 item->key_idx = atoi(tmp_str);
577 pmix_list_append(&key_replace, &item->super);
578 }
579 } else {
580 ret = 1;
581 break;
582 }
583 }
584 free(tmp);
585 return ret;
586 }
587
588 int get_total_ns_number(test_params params)
589 {
590 int num = 0;
591 if (NULL == params.ns_dist) {
592 return 1;
593 } else {
594 char *tmp = strdup(params.ns_dist);
595 char *pch = tmp;
596 while (NULL != pch) {
597 num++;
598 pch = strtok((1 == num ) ? tmp : NULL, ":");
599 }
600 num--;
601 free(tmp);
602 }
603 return num;
604 }
605
606 int get_all_ranks_from_namespace(test_params params, char *nspace, pmix_proc_t **ranks, size_t *nranks)
607 {
608 size_t num_ranks = 0;
609 int num = -1;
610 size_t j;
611 if (NULL == params.ns_dist) {
612 *nranks = params.ns_size;
613 PMIX_PROC_CREATE(*ranks, params.ns_size);
614 for (j = 0; j < (size_t)params.ns_size; j++) {
615 (void)strncpy((*ranks)[j].nspace, nspace, PMIX_MAX_NSLEN);
616 (*ranks)[j].rank = j;
617 }
618 } else {
619 char *tmp = strdup(params.ns_dist);
620 char *pch = tmp;
621 int ns_id = (int)strtol(nspace + strlen(TEST_NAMESPACE) + 1, NULL, 10);
622 while (NULL != pch && num != ns_id) {
623 pch = strtok((-1 == num ) ? tmp : NULL, ":");
624 if (NULL == pch) {
625 break;
626 }
627 num++;
628 num_ranks = (size_t)strtol(pch, NULL, 10);
629 }
630 if (num == ns_id && 0 != num_ranks) {
631 *nranks = num_ranks;
632 PMIX_PROC_CREATE(*ranks, num_ranks);
633 for (j = 0; j < num_ranks; j++) {
634 (void)strncpy((*ranks)[j].nspace, nspace, PMIX_MAX_NSLEN);
635 (*ranks)[j].rank = j;
636 }
637 } else {
638 free(tmp);
639 return PMIX_ERROR;
640 }
641 free(tmp);
642 }
643 return PMIX_SUCCESS;
644 }