This source file includes following definitions.
- generate_node_regex
- generate_ppn
- parse_nodes
- parse_procs
- resolve_peers
- resolve_nodes
- pmix_regex_extract_nodes
- regex_parse_value_ranges
- regex_parse_value_range
- pmix_regex_extract_ppn
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #include <src/include/pmix_config.h>
15
16 #ifdef HAVE_STRING_H
17 #include <string.h>
18 #endif
19 #include <fcntl.h>
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23 #ifdef HAVE_SYS_TYPES_H
24 #include <sys/types.h>
25 #endif
26 #include <ctype.h>
27
28
29 #include <pmix_common.h>
30 #include <pmix.h>
31
32 #include "src/include/pmix_socket_errno.h"
33 #include "src/include/pmix_globals.h"
34 #include "src/util/argv.h"
35 #include "src/util/error.h"
36 #include "src/util/output.h"
37 #include "src/class/pmix_list.h"
38 #include "src/mca/gds/gds.h"
39 #include "src/client/pmix_client_ops.h"
40
41 #include "src/mca/preg/preg.h"
42 #include "preg_native.h"
43
44 static pmix_status_t generate_node_regex(const char *input,
45 char **regex);
46 static pmix_status_t generate_ppn(const char *input,
47 char **ppn);
48 static pmix_status_t parse_nodes(const char *regexp,
49 char ***names);
50 static pmix_status_t parse_procs(const char *regexp,
51 char ***procs);
52 static pmix_status_t resolve_peers(const char *nodename,
53 const char *nspace,
54 pmix_proc_t **procs, size_t *nprocs);
55 static pmix_status_t resolve_nodes(const char *nspace,
56 char **nodelist);
57
58 pmix_preg_module_t pmix_preg_native_module = {
59 .name = "pmix",
60 .generate_node_regex = generate_node_regex,
61 .generate_ppn = generate_ppn,
62 .parse_nodes = parse_nodes,
63 .parse_procs = parse_procs,
64 .resolve_peers = resolve_peers,
65 .resolve_nodes = resolve_nodes
66 };
67
68 static pmix_status_t regex_parse_value_ranges(char *base, char *ranges,
69 int num_digits, char *suffix,
70 char ***names);
71 static pmix_status_t regex_parse_value_range(char *base, char *range,
72 int num_digits, char *suffix,
73 char ***names);
74 static pmix_status_t pmix_regex_extract_nodes(char *regexp, char ***names);
75 static pmix_status_t pmix_regex_extract_ppn(char *regexp, char ***procs);
76
77
78 static pmix_status_t generate_node_regex(const char *input,
79 char **regexp)
80 {
81 char *vptr, *vsave;
82 char prefix[PMIX_MAX_NODE_PREFIX];
83 int i, j, len, startnum, vnum, numdigits;
84 bool found, fullval;
85 char *suffix, *sfx;
86 pmix_regex_value_t *vreg;
87 pmix_regex_range_t *range;
88 pmix_list_t vids;
89 char **regexargs = NULL, *tmp, *tmp2;
90 char *cptr;
91
92
93 *regexp = NULL;
94
95
96 PMIX_CONSTRUCT(&vids, pmix_list_t);
97
98
99
100 vsave = strdup(input);
101 vptr = vsave;
102 while (NULL != (cptr = strchr(vptr, ',')) || 0 < strlen(vptr)) {
103 if (NULL != cptr) {
104 *cptr = '\0';
105 }
106
107 fullval = false;
108 len = strlen(vptr);
109 startnum = -1;
110 memset(prefix, 0, PMIX_MAX_NODE_PREFIX);
111 for (i=0, j=0; i < len; i++) {
112 if (!isalpha(vptr[i])) {
113
114 if (!isdigit(vptr[i])) {
115
116
117
118 fullval = true;
119 break;
120 }
121
122
123
124 if (startnum < 0) {
125
126 startnum = i;
127 }
128 continue;
129 }
130 if (startnum < 0) {
131 prefix[j++] = vptr[i];
132 }
133 }
134 if (fullval || startnum < 0) {
135
136 vreg = PMIX_NEW(pmix_regex_value_t);
137 vreg->prefix = strdup(vptr);
138 pmix_list_append(&vids, &vreg->super);
139
140 if (NULL == cptr) {
141 break;
142 }
143 vptr = cptr + 1;
144 continue;
145 }
146
147 vnum = strtol(&vptr[startnum], &sfx, 10);
148 if (NULL != sfx) {
149 suffix = strdup(sfx);
150 numdigits = (int)(sfx - &vptr[startnum]);
151 } else {
152 suffix = NULL;
153 numdigits = (int)strlen(&vptr[startnum]);
154 }
155
156
157 found = false;
158 PMIX_LIST_FOREACH(vreg, &vids, pmix_regex_value_t) {
159
160
161
162
163
164
165
166
167 if( vreg->skip ) {
168 continue;
169 }
170
171 if (0 < strlen(prefix) && NULL == vreg->prefix) {
172 continue;
173 }
174 if (0 == strlen(prefix) && NULL != vreg->prefix) {
175 continue;
176 }
177 if (0 < strlen(prefix) && NULL != vreg->prefix
178 && 0 != strcmp(prefix, vreg->prefix)) {
179 vreg->skip = true;
180 continue;
181 }
182 if (NULL == suffix && NULL != vreg->suffix) {
183 continue;
184 }
185 if (NULL != suffix && NULL == vreg->suffix) {
186 continue;
187 }
188 if (NULL != suffix && NULL != vreg->suffix &&
189 0 != strcmp(suffix, vreg->suffix)) {
190 vreg->skip = true;
191 continue;
192 }
193 if (numdigits != vreg->num_digits) {
194 vreg->skip = true;
195 continue;
196 }
197
198 found = true;
199
200
201
202 range = (pmix_regex_range_t*)pmix_list_get_last(&vreg->ranges);
203 if (NULL == range) {
204
205 range = PMIX_NEW(pmix_regex_range_t);
206 range->start = vnum;
207 range->cnt = 1;
208 pmix_list_append(&vreg->ranges, &range->super);
209 break;
210 }
211
212 if (vnum != (range->start + range->cnt)) {
213
214 range = PMIX_NEW(pmix_regex_range_t);
215 range->start = vnum;
216 range->cnt = 1;
217 pmix_list_append(&vreg->ranges, &range->super);
218 break;
219 }
220
221 range->cnt++;
222 break;
223 }
224 if (!found) {
225
226 vreg = PMIX_NEW(pmix_regex_value_t);
227 if (0 < strlen(prefix)) {
228 vreg->prefix = strdup(prefix);
229 }
230 if (NULL != suffix) {
231 vreg->suffix = strdup(suffix);
232 }
233 vreg->num_digits = numdigits;
234 pmix_list_append(&vids, &vreg->super);
235
236
237
238 range = PMIX_NEW(pmix_regex_range_t);
239 range->start = vnum;
240 range->cnt = 1;
241 pmix_list_append(&vreg->ranges, &range->super);
242 }
243 if (NULL != suffix) {
244 free(suffix);
245 }
246
247 if (NULL == cptr) {
248 break;
249 }
250 vptr = cptr + 1;
251 }
252 free(vsave);
253
254
255 while (NULL != (vreg = (pmix_regex_value_t*)pmix_list_remove_first(&vids))) {
256
257 if (0 == pmix_list_get_size(&vreg->ranges)) {
258 if (NULL != vreg->prefix) {
259 pmix_argv_append_nosize(®exargs, vreg->prefix);
260 }
261 PMIX_RELEASE(vreg);
262 continue;
263 }
264
265 if (NULL != vreg->prefix) {
266 if (0 > asprintf(&tmp, "%s[%d:", vreg->prefix, vreg->num_digits)) {
267 return PMIX_ERR_NOMEM;
268 }
269 } else {
270 if (0 > asprintf(&tmp, "[%d:", vreg->num_digits)) {
271 return PMIX_ERR_NOMEM;
272 }
273 }
274
275 while (NULL != (range = (pmix_regex_range_t*)pmix_list_remove_first(&vreg->ranges))) {
276 if (1 == range->cnt) {
277 if (0 > asprintf(&tmp2, "%s%d,", tmp, range->start)) {
278 return PMIX_ERR_NOMEM;
279 }
280 } else {
281 if (0 > asprintf(&tmp2, "%s%d-%d,", tmp, range->start, range->start + range->cnt - 1)) {
282 return PMIX_ERR_NOMEM;
283 }
284 }
285 free(tmp);
286 tmp = tmp2;
287 PMIX_RELEASE(range);
288 }
289
290 tmp[strlen(tmp)-1] = ']';
291 if (NULL != vreg->suffix) {
292
293 if (0 > asprintf(&tmp2, "%s%s", tmp, vreg->suffix)) {
294 return PMIX_ERR_NOMEM;
295 }
296 free(tmp);
297 tmp = tmp2;
298 }
299 pmix_argv_append_nosize(®exargs, tmp);
300 free(tmp);
301 PMIX_RELEASE(vreg);
302 }
303
304
305 tmp = pmix_argv_join(regexargs, ',');
306 if (0 > asprintf(regexp, "pmix[%s]", tmp)) {
307 return PMIX_ERR_NOMEM;
308 }
309 free(tmp);
310
311
312 pmix_argv_free(regexargs);
313
314 PMIX_DESTRUCT(&vids);
315 return PMIX_SUCCESS;
316 }
317
318 static pmix_status_t generate_ppn(const char *input,
319 char **regexp)
320 {
321 char **ppn, **npn;
322 int i, j, start, end;
323 pmix_regex_value_t *vreg;
324 pmix_regex_range_t *rng;
325 pmix_list_t nodes;
326 char *tmp, *tmp2;
327 char *cptr;
328
329
330 *regexp = NULL;
331
332
333 PMIX_CONSTRUCT(&nodes, pmix_list_t);
334
335
336 ppn = pmix_argv_split(input, ';');
337
338
339 for (i=0; NULL != ppn[i]; i++) {
340 rng = NULL;
341
342 vreg = PMIX_NEW(pmix_regex_value_t);
343 pmix_list_append(&nodes, &vreg->super);
344
345 npn = pmix_argv_split(ppn[i], ',');
346
347 for (j=0; NULL != npn[j]; j++) {
348
349 if (NULL != (cptr = strchr(npn[j], '-'))) {
350
351 *cptr = '\0';
352 ++cptr;
353 start = strtol(npn[j], NULL, 10);
354 end = strtol(cptr, NULL, 10);
355
356 if (NULL == rng) {
357
358 rng = PMIX_NEW(pmix_regex_range_t);
359 rng->start = start;
360 rng->cnt = end - start + 1;
361 pmix_list_append(&vreg->ranges, &rng->super);
362 } else {
363
364 if (start == (rng->start + rng->cnt)) {
365
366 rng->cnt++;
367 } else {
368
369 rng = PMIX_NEW(pmix_regex_range_t);
370 rng->start = start;
371 rng->cnt = end - start + 1;
372 pmix_list_append(&vreg->ranges, &rng->super);
373 }
374 }
375 } else {
376
377 start = strtol(npn[j], NULL, 10);
378
379 if (NULL == rng) {
380
381 rng = PMIX_NEW(pmix_regex_range_t);
382 rng->start = start;
383 rng->cnt = 1;
384 pmix_list_append(&vreg->ranges, &rng->super);
385 } else {
386
387 if (start == (rng->start + rng->cnt)) {
388
389 rng->cnt++;
390 } else {
391
392 rng = PMIX_NEW(pmix_regex_range_t);
393 rng->start = start;
394 rng->cnt = 1;
395 pmix_list_append(&vreg->ranges, &rng->super);
396 }
397 }
398 }
399 }
400 pmix_argv_free(npn);
401 }
402 pmix_argv_free(ppn);
403
404
405
406 tmp = strdup("pmix[");
407 PMIX_LIST_FOREACH(vreg, &nodes, pmix_regex_value_t) {
408 while (NULL != (rng = (pmix_regex_range_t*)pmix_list_remove_first(&vreg->ranges))) {
409 if (1 == rng->cnt) {
410 if (0 > asprintf(&tmp2, "%s%d,", tmp, rng->start)) {
411 return PMIX_ERR_NOMEM;
412 }
413 } else {
414 if (0 > asprintf(&tmp2, "%s%d-%d,", tmp, rng->start, rng->start + rng->cnt - 1)) {
415 return PMIX_ERR_NOMEM;
416 }
417 }
418 free(tmp);
419 tmp = tmp2;
420 PMIX_RELEASE(rng);
421 }
422
423 tmp[strlen(tmp)-1] = ';';
424 }
425
426
427 tmp[strlen(tmp)-1] = ']';
428
429
430 *regexp = tmp;
431
432 PMIX_LIST_DESTRUCT(&nodes);
433 return PMIX_SUCCESS;
434 }
435
436 static pmix_status_t parse_nodes(const char *regexp,
437 char ***names)
438 {
439 char *tmp, *ptr;
440 pmix_status_t rc;
441
442
443 *names = NULL;
444
445
446 if (NULL == regexp) {
447 return PMIX_SUCCESS;
448 }
449
450
451 tmp = strdup(regexp);
452
453 tmp[strlen(tmp)-1] = '\0';
454
455
456
457 if (NULL == (ptr = strchr(tmp, '['))) {
458 PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM);
459 free(tmp);
460 return PMIX_ERR_BAD_PARAM;
461 }
462 *ptr = '\0';
463 ++ptr;
464
465
466 if (0 == strcmp(tmp, "pmix")) {
467 if (PMIX_SUCCESS != (rc = pmix_regex_extract_nodes(ptr, names))) {
468 PMIX_ERROR_LOG(rc);
469 }
470 } else {
471
472 rc = PMIX_ERR_TAKE_NEXT_OPTION;
473 }
474 free(tmp);
475 return rc;
476
477 }
478 static pmix_status_t parse_procs(const char *regexp,
479 char ***procs)
480 {
481 char *tmp, *ptr;
482 pmix_status_t rc;
483
484
485 *procs = NULL;
486
487
488 if (NULL == regexp) {
489 return PMIX_SUCCESS;
490 }
491
492
493 tmp = strdup(regexp);
494
495 tmp[strlen(tmp)-1] = '\0';
496
497
498
499 if (NULL == (ptr = strchr(tmp, '['))) {
500 PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM);
501 free(tmp);
502 return PMIX_ERR_BAD_PARAM;
503 }
504 *ptr = '\0';
505 ++ptr;
506
507
508 if (0 == strcmp(tmp, "pmix")) {
509 if (PMIX_SUCCESS != (rc = pmix_regex_extract_ppn(ptr, procs))) {
510 PMIX_ERROR_LOG(rc);
511 }
512 } else {
513
514 rc = PMIX_ERR_TAKE_NEXT_OPTION;
515 }
516 free(tmp);
517 return rc;
518 }
519
520 static pmix_status_t resolve_peers(const char *nodename,
521 const char *nspace,
522 pmix_proc_t **procs, size_t *nprocs)
523 {
524 pmix_cb_t cb;
525 pmix_status_t rc;
526 pmix_kval_t *kv;
527 pmix_proc_t proc;
528 char **ptr;
529 pmix_info_t *info;
530 pmix_proc_t *p=NULL;
531 size_t ninfo, np=0, n, j;
532
533 PMIX_CONSTRUCT(&cb, pmix_cb_t);
534
535 cb.key = strdup(nodename);
536
537 cb.copy = false;
538
539 cb.scope = PMIX_SCOPE_UNDEF;
540
541 pmix_strncpy(proc.nspace, nspace, PMIX_MAX_NSLEN);
542 proc.rank = PMIX_RANK_WILDCARD;
543 cb.proc = &proc;
544
545 PMIX_GDS_FETCH_KV(rc, pmix_client_globals.myserver, &cb);
546 if (PMIX_SUCCESS != rc) {
547 if (PMIX_ERR_INVALID_NAMESPACE != rc) {
548 PMIX_ERROR_LOG(rc);
549 }
550 goto complete;
551 }
552
553 if (1 != pmix_list_get_size(&cb.kvs)) {
554 PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM);
555 rc = PMIX_ERR_BAD_PARAM;
556 goto complete;
557 }
558 kv = (pmix_kval_t*)pmix_list_get_first(&cb.kvs);
559
560
561 if (NULL == kv->value ||
562 PMIX_DATA_ARRAY != kv->value->type ||
563 NULL == kv->value->data.darray ||
564 PMIX_INFO != kv->value->data.darray->type) {
565 PMIX_ERROR_LOG(PMIX_ERR_DATA_VALUE_NOT_FOUND);
566 rc = PMIX_ERR_DATA_VALUE_NOT_FOUND;
567 goto complete;
568 }
569 info = (pmix_info_t*)kv->value->data.darray->array;
570 ninfo = kv->value->data.darray->size;
571
572 for (n=0; n < ninfo; n++) {
573 if (0 == strncmp(info[n].key, PMIX_LOCAL_PEERS, PMIX_MAX_KEYLEN)) {
574
575 ptr = pmix_argv_split(info[n].value.data.string, ',');
576 np = pmix_argv_count(ptr);
577 PMIX_PROC_CREATE(p, np);
578 if (NULL == p) {
579 rc = PMIX_ERR_NOMEM;
580 pmix_argv_free(ptr);
581 goto complete;
582 }
583 for (j=0; j < np; j++) {
584 pmix_strncpy(p[j].nspace, nspace, PMIX_MAX_NSLEN);
585 p[j].rank = strtoul(ptr[j], NULL, 10);
586 }
587 rc = PMIX_SUCCESS;
588 pmix_argv_free(ptr);
589 break;
590 }
591 }
592
593 complete:
594 if (NULL != cb.info) {
595 PMIX_INFO_FREE(cb.info, cb.ninfo);
596 }
597 if (NULL != cb.key) {
598 free(cb.key);
599 cb.key = NULL;
600 }
601 PMIX_DESTRUCT(&cb);
602 *procs = p;
603 *nprocs = np;
604
605 return rc;
606 }
607
608 static pmix_status_t resolve_nodes(const char *nspace,
609 char **nodelist)
610 {
611 pmix_cb_t cb;
612 pmix_status_t rc;
613 pmix_kval_t *kv;
614 pmix_proc_t proc;
615
616 PMIX_CONSTRUCT(&cb, pmix_cb_t);
617
618
619 *nodelist = NULL;
620
621
622
623 PMIX_INFO_CREATE(cb.info, 1);
624 if (NULL == cb.info) {
625 PMIX_DESTRUCT(&cb);
626 return PMIX_ERR_NOMEM;
627 }
628 cb.ninfo = 1;
629 PMIX_INFO_LOAD(&cb.info[0], PMIX_NSPACE, nspace, PMIX_STRING);
630
631
632 cb.key = PMIX_NODE_MAP;
633
634 cb.copy = false;
635
636 cb.scope = PMIX_SCOPE_UNDEF;
637
638 pmix_strncpy(proc.nspace, nspace, PMIX_MAX_NSLEN);
639
640 proc.rank = PMIX_RANK_WILDCARD;
641 cb.proc = &proc;
642
643 PMIX_GDS_FETCH_KV(rc, pmix_client_globals.myserver, &cb);
644 if (PMIX_SUCCESS != rc) {
645 PMIX_ERROR_LOG(rc);
646 goto complete;
647 }
648
649 if (1 != pmix_list_get_size(&cb.kvs)) {
650 PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM);
651 rc = PMIX_ERR_BAD_PARAM;
652 goto complete;
653 }
654 kv = (pmix_kval_t*)pmix_list_get_first(&cb.kvs);
655
656
657 if (NULL == kv->value ||
658 PMIX_STRING != kv->value->type) {
659 PMIX_ERROR_LOG(PMIX_ERR_DATA_VALUE_NOT_FOUND);
660 rc = PMIX_ERR_DATA_VALUE_NOT_FOUND;
661 goto complete;
662 }
663
664 if (NULL != kv->value->data.string) {
665 *nodelist = strdup(kv->value->data.string);
666 }
667
668 complete:
669 if (NULL != cb.info) {
670 PMIX_INFO_FREE(cb.info, cb.ninfo);
671 }
672 return rc;
673 }
674
675 static pmix_status_t pmix_regex_extract_nodes(char *regexp, char ***names)
676 {
677 int i, j, k, len;
678 pmix_status_t ret;
679 char *base;
680 char *orig, *suffix;
681 bool found_range = false;
682 bool more_to_come = false;
683 int num_digits;
684
685
686 *names = NULL;
687
688 if (NULL == regexp) {
689 return PMIX_SUCCESS;
690 }
691
692 orig = base = strdup(regexp);
693 if (NULL == base) {
694 PMIX_ERROR_LOG(PMIX_ERR_OUT_OF_RESOURCE);
695 return PMIX_ERR_OUT_OF_RESOURCE;
696 }
697
698 PMIX_OUTPUT_VERBOSE((1, pmix_globals.debug_output,
699 "pmix:extract:nodes: checking list: %s", regexp));
700
701 do {
702
703 len = strlen(base);
704 for (i = 0; i <= len; ++i) {
705 if (base[i] == '[') {
706
707 base[i] = '\0';
708 found_range = true;
709 break;
710 }
711 if (base[i] == ',') {
712
713 base[i] = '\0';
714 found_range = false;
715 more_to_come = true;
716 break;
717 }
718 if (base[i] == '\0') {
719
720 found_range = false;
721 more_to_come = false;
722 break;
723 }
724 }
725 if (i == 0 && !found_range) {
726
727 free(orig);
728 return PMIX_ERR_BAD_PARAM;
729 }
730
731 if (found_range) {
732
733 i++;
734 for (j=i; j < len; j++) {
735 if (base[j] == ':') {
736 base[j] = '\0';
737 break;
738 }
739 }
740 if (j >= len) {
741
742 free(orig);
743 return PMIX_ERR_BAD_PARAM;
744 }
745 num_digits = strtol(&base[i], NULL, 10);
746 i = j + 1;
747
748 for (j = i; j < len; ++j) {
749 if (base[j] == ']') {
750 base[j] = '\0';
751 break;
752 }
753 }
754 if (j >= len) {
755
756 free(orig);
757 return PMIX_ERR_BAD_PARAM;
758 }
759
760 if (j+1 < len && base[j+1] != ',') {
761
762 for (k=j+1; k < len && base[k] != ','; k++);
763 if (k < len) {
764 base[k] = '\0';
765 }
766 suffix = strdup(&base[j+1]);
767 if (k < len) {
768 base[k] = ',';
769 }
770 j = k-1;
771 } else {
772 suffix = NULL;
773 }
774 PMIX_OUTPUT_VERBOSE((1, pmix_globals.debug_output,
775 "regex:extract:nodes: parsing range %s %s %s",
776 base, base + i, suffix));
777
778 ret = regex_parse_value_ranges(base, base + i, num_digits, suffix, names);
779 if (NULL != suffix) {
780 free(suffix);
781 }
782 if (PMIX_SUCCESS != ret) {
783 free(orig);
784 return ret;
785 }
786 if (j+1 < len && base[j + 1] == ',') {
787 more_to_come = true;
788 base = &base[j + 2];
789 } else {
790 more_to_come = false;
791 }
792 } else {
793
794 if(PMIX_SUCCESS != (ret = pmix_argv_append_nosize(names, base))) {
795 PMIX_ERROR_LOG(ret);
796 free(orig);
797 return ret;
798 }
799
800 i++;
801
802 base = &base[i];
803 }
804 } while(more_to_come);
805
806 free(orig);
807
808
809 return ret;
810 }
811
812
813
814
815
816
817
818
819
820
821 static pmix_status_t regex_parse_value_ranges(char *base, char *ranges,
822 int num_digits, char *suffix,
823 char ***names)
824 {
825 int i, len;
826 pmix_status_t ret;
827 char *start, *orig;
828
829
830
831 len = strlen(ranges);
832 for (orig = start = ranges, i = 0; i < len; ++i) {
833 if (',' == ranges[i]) {
834 ranges[i] = '\0';
835 ret = regex_parse_value_range(base, start, num_digits, suffix, names);
836 if (PMIX_SUCCESS != ret) {
837 PMIX_ERROR_LOG(ret);
838 return ret;
839 }
840 start = ranges + i + 1;
841 }
842 }
843
844
845
846 if (start < orig + len) {
847
848 PMIX_OUTPUT_VERBOSE((1, pmix_globals.debug_output,
849 "regex:parse:ranges: parse range %s (2)", start));
850
851 ret = regex_parse_value_range(base, start, num_digits, suffix, names);
852 if (PMIX_SUCCESS != ret) {
853 PMIX_ERROR_LOG(ret);
854 return ret;
855 }
856 }
857
858
859 return PMIX_SUCCESS;
860 }
861
862
863
864
865
866
867
868
869
870
871 static pmix_status_t regex_parse_value_range(char *base, char *range,
872 int num_digits, char *suffix,
873 char ***names)
874 {
875 char *str, tmp[132];
876 size_t i, k, start, end;
877 size_t base_len, len;
878 bool found;
879 pmix_status_t ret;
880
881 if (NULL == base || NULL == range) {
882 return PMIX_ERROR;
883 }
884
885 len = strlen(range);
886 base_len = strlen(base);
887
888
889 start = end = 0;
890
891
892
893 for (found = false, i = 0; i < len; ++i) {
894 if (isdigit((int) range[i])) {
895 if (!found) {
896 start = atoi(range + i);
897 found = true;
898 break;
899 }
900 }
901 }
902 if (!found) {
903 PMIX_ERROR_LOG(PMIX_ERR_NOT_FOUND);
904 return PMIX_ERR_NOT_FOUND;
905 }
906
907
908
909 for (found = false; i < len; ++i) {
910 if (!isdigit(range[i])) {
911 break;
912 }
913 }
914
915
916
917 if (i >= len) {
918 end = start;
919 found = true;
920 } else {
921
922
923
924 for (; i < len; ++i) {
925 if (isdigit(range[i])) {
926 end = strtol(range + i, NULL, 10);
927 found = true;
928 break;
929 }
930 }
931 }
932 if (!found) {
933 PMIX_ERROR_LOG(PMIX_ERR_NOT_FOUND);
934 return PMIX_ERR_NOT_FOUND;
935 }
936
937
938
939 len = base_len + num_digits + 32;
940 if (NULL != suffix) {
941 len += strlen(suffix);
942 }
943 str = (char *) malloc(len);
944 if (NULL == str) {
945 PMIX_ERROR_LOG(PMIX_ERR_OUT_OF_RESOURCE);
946 return PMIX_ERR_OUT_OF_RESOURCE;
947 }
948 for (i = start; i <= end; ++i) {
949 memset(str, 0, len);
950 strcpy(str, base);
951
952 for (k=0; k < (size_t)num_digits; k++) {
953 str[k+base_len] = '0';
954 }
955 memset(tmp, 0, 132);
956 snprintf(tmp, 132, "%lu", (unsigned long)i);
957 for (k=0; k < strlen(tmp); k++) {
958 str[base_len + num_digits - k - 1] = tmp[strlen(tmp)-k-1];
959 }
960
961 if (NULL != suffix) {
962 strcat(str, suffix);
963 }
964 ret = pmix_argv_append_nosize(names, str);
965 if(PMIX_SUCCESS != ret) {
966 PMIX_ERROR_LOG(ret);
967 free(str);
968 return ret;
969 }
970 }
971 free(str);
972
973
974 return PMIX_SUCCESS;
975 }
976
977 static pmix_status_t pmix_regex_extract_ppn(char *regexp, char ***procs)
978 {
979 char **rngs, **nds, *t, **ps=NULL;
980 int i, j, k, start, end;
981
982
983 nds = pmix_argv_split(regexp, ';');
984 for (j=0; NULL != nds[j]; j++) {
985
986 rngs = pmix_argv_split(nds[j], ',');
987
988 for (i=0; NULL != rngs[i]; i++) {
989
990 if (NULL == (t = strchr(rngs[i], '-'))) {
991
992 pmix_argv_append_nosize(&ps, rngs[i]);
993 } else {
994
995 *t = '\0';
996 start = strtol(rngs[i], NULL, 10);
997 ++t;
998 end = strtol(t, NULL, 10);
999 for (k=start; k <= end; k++) {
1000 if (0 > asprintf(&t, "%d", k)) {
1001 pmix_argv_free(nds);
1002 pmix_argv_free(rngs);
1003 return PMIX_ERR_NOMEM;
1004 }
1005 pmix_argv_append_nosize(&ps, t);
1006 free(t);
1007 }
1008 }
1009 }
1010 pmix_argv_free(rngs);
1011
1012 t = pmix_argv_join(ps, ',');
1013 pmix_argv_append_nosize(procs, t);
1014 free(t);
1015 pmix_argv_free(ps);
1016 ps = NULL;
1017 }
1018
1019 pmix_argv_free(nds);
1020 return PMIX_SUCCESS;
1021 }