00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "adio.h"
00021 #include "mpi.h"
00022 #include "adio_cb_config_list.h"
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <stdlib.h>
00026
00027 #include "converse.h"
00028
00029
00030 #define AGG_WILDCARD 1
00031 #define AGG_STRING 2
00032 #define AGG_COMMA 3
00033 #define AGG_COLON 4
00034 #define AGG_ERROR -1
00035 #define AGG_EOS 0
00036
00037 #undef CB_CONFIG_LIST_DEBUG
00038
00039
00040
00041 CtvDeclare(int, ADIOI_cb_config_list_keyval);
00042 CtvStaticDeclare(char*, yylval);
00043 CtvStaticDeclare(char*, token_ptr);
00044
00045
00046
00047 CtvStaticDeclare(int, cb_config_list_keyval_init_done);
00048
00049
00050 static int get_max_procs(int cb_nodes);
00051 static int match_procs(char *name, int max_per_proc, char *procnames[],
00052 char used_procnames[],
00053 int nr_procnames, int ranks[], int nr_ranks,
00054 int *nr_ranks_allocated);
00055 static int match_this_proc(char *name, int cur_proc, int max_matches,
00056 char *procnames[], char used_procnames[],
00057 int nr_procnames, int ranks[],
00058 int nr_ranks, int nr_ranks_allocated);
00059 static int find_name(char *name, char *procnames[], char used_procnames[],
00060 int nr_procnames, int start_ind);
00061 static int cb_config_list_lex(void);
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 int ADIOI_cb_bcast_rank_map(ADIO_File fd)
00073 {
00074 int my_rank;
00075 char *value;
00076
00077 MPI_Bcast(&(fd->hints->cb_nodes), 1, MPI_INT, 0, fd->comm);
00078 if (fd->hints->cb_nodes > 0) {
00079 MPI_Comm_rank(fd->comm, &my_rank);
00080 if (my_rank != 0) {
00081 fd->hints->ranklist = ADIOI_Malloc(fd->hints->cb_nodes*sizeof(int));
00082 if (fd->hints->ranklist == NULL) {
00083
00084 }
00085 }
00086 MPI_Bcast(fd->hints->ranklist, fd->hints->cb_nodes, MPI_INT, 0,
00087 fd->comm);
00088 }
00089
00090
00091 value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char));
00092 ADIOI_Snprintf(value, MPI_MAX_INFO_VAL+1, "%d", fd->hints->cb_nodes);
00093 ADIOI_Info_set(fd->info, "cb_nodes", value);
00094 ADIOI_Free(value);
00095
00096 return 0;
00097 }
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 int ADIOI_cb_gather_name_array(MPI_Comm comm,
00112 MPI_Comm dupcomm,
00113 ADIO_cb_name_array *arrayp)
00114 {
00115 char my_procname[MPI_MAX_PROCESSOR_NAME], **procname = 0;
00116 int *procname_len = NULL, my_procname_len, *disp = NULL, i;
00117 int commsize, commrank, found;
00118 ADIO_cb_name_array array = NULL;
00119 int alloc_size;
00120
00121
00122
00123 CtvInitialize(int, cb_config_list_keyval_init_done);
00124
00125 if (CtvAccess(cb_config_list_keyval_init_done) != 1) {
00126 CtvAccess(cb_config_list_keyval_init_done) = 1;
00127 CtvInitialize(int, ADIOI_cb_config_list_keyval);
00128 CtvAccess(ADIOI_cb_config_list_keyval) = MPI_KEYVAL_INVALID;
00129 }
00130
00131 if (CtvAccess(ADIOI_cb_config_list_keyval) == MPI_KEYVAL_INVALID) {
00132
00133 MPI_Keyval_create((MPI_Copy_function *) ADIOI_cb_copy_name_array,
00134 (MPI_Delete_function *) ADIOI_cb_delete_name_array,
00135 &CtvAccess(ADIOI_cb_config_list_keyval), NULL);
00136 }
00137 else {
00138 MPI_Attr_get(comm, CtvAccess(ADIOI_cb_config_list_keyval), (void *) &array, &found);
00139 if (found) {
00140 ADIOI_Assert(array != NULL);
00141 *arrayp = array;
00142 return 0;
00143 }
00144 }
00145
00146 MPI_Comm_size(dupcomm, &commsize);
00147 MPI_Comm_rank(dupcomm, &commrank);
00148
00149 MPI_Get_processor_name(my_procname, &my_procname_len);
00150
00151
00152 array = (ADIO_cb_name_array) ADIOI_Malloc(sizeof(*array));
00153 if (array == NULL) {
00154 return -1;
00155 }
00156 array->refct = 2;
00157
00158 if (commrank == 0) {
00159
00160 array->namect = commsize;
00161
00162 array->names = (char **) ADIOI_Malloc(sizeof(char *) * commsize);
00163 if (array->names == NULL) {
00164 return -1;
00165 }
00166 procname = array->names;
00167
00168 procname_len = (int *) ADIOI_Malloc(commsize * sizeof(int));
00169 if (procname_len == NULL) {
00170 return -1;
00171 }
00172 }
00173 else {
00174
00175 array->namect = 0;
00176 array->names = NULL;
00177 }
00178
00179 MPI_Gather(&my_procname_len, 1, MPI_INT,
00180 procname_len, 1, MPI_INT, 0, dupcomm);
00181
00182 if (commrank == 0) {
00183 #ifdef CB_CONFIG_LIST_DEBUG
00184 for (i=0; i < commsize; i++) {
00185 FPRINTF(stderr, "len[%d] = %d\n", i, procname_len[i]);
00186 }
00187 #endif
00188
00189 alloc_size = 0;
00190 for (i=0; i < commsize; i++) {
00191
00192
00193
00194
00195 alloc_size += ++procname_len[i];
00196 }
00197
00198 procname[0] = ADIOI_Malloc(alloc_size);
00199 if (procname[0] == NULL) {
00200 return -1;
00201 }
00202
00203 for (i=1; i < commsize; i++) {
00204 procname[i] = procname[i-1] + procname_len[i-1];
00205 }
00206
00207
00208
00209
00210
00211 disp = ADIOI_Malloc(commsize * sizeof(int));
00212 disp[0] = 0;
00213 for (i=1; i < commsize; i++) {
00214 disp[i] = (int) (procname[i] - procname[0]);
00215 }
00216
00217 }
00218
00219
00220 if (commrank == 0) {
00221 MPI_Gatherv(my_procname, my_procname_len + 1, MPI_CHAR,
00222 procname[0], procname_len, disp, MPI_CHAR,
00223 0, dupcomm);
00224 }
00225 else {
00226
00227
00228
00229 MPI_Gatherv(my_procname, my_procname_len + 1, MPI_CHAR,
00230 NULL, NULL, NULL, MPI_CHAR, 0, dupcomm);
00231 }
00232
00233 if (commrank == 0) {
00234
00235 ADIOI_Free(disp);
00236 ADIOI_Free(procname_len);
00237
00238 #ifdef CB_CONFIG_LIST_DEBUG
00239 for (i=0; i < commsize; i++) {
00240 FPRINTF(stderr, "name[%d] = %s\n", i, procname[i]);
00241 }
00242 #endif
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 MPI_Attr_put(comm, CtvAccess(ADIOI_cb_config_list_keyval), array);
00254 MPI_Attr_put(dupcomm, CtvAccess(ADIOI_cb_config_list_keyval), array);
00255 *arrayp = array;
00256 return 0;
00257 }
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 int ADIOI_cb_config_list_parse(char *config_list,
00269 ADIO_cb_name_array array,
00270 int ranklist[],
00271 int cb_nodes)
00272 {
00273 int token, max_procs, cur_rank = 0, nr_procnames;
00274 char *cur_procname, *cur_procname_p, **procnames;
00275 char *used_procnames;
00276
00277 nr_procnames = array->namect;
00278 procnames = array->names;
00279
00280
00281
00282
00283
00284 cur_procname = ADIOI_Malloc((MPI_MAX_INFO_VAL+1) * sizeof(char));
00285 if (cur_procname == NULL) {
00286 return -1;
00287 }
00288 CtvInitialize(char*, yylval);
00289 CtvAccess(yylval) = ADIOI_Malloc((MPI_MAX_INFO_VAL+1) * sizeof(char));
00290 if (CtvAccess(yylval) == NULL) {
00291 ADIOI_Free(cur_procname);
00292 return -1;
00293 }
00294
00295 CtvInitialize(char*, token_ptr);
00296 CtvAccess(token_ptr) = config_list;
00297
00298
00299 if (cb_nodes > nr_procnames) cb_nodes = nr_procnames;
00300
00301
00302
00303
00304 used_procnames = ADIOI_Malloc(array->namect * sizeof(char));
00305 if (used_procnames == NULL) {
00306 ADIOI_Free(cur_procname);
00307 ADIOI_Free(CtvAccess(yylval));
00308 CtvAccess(yylval) = NULL;
00309 return -1;
00310 }
00311 memset(used_procnames, 0, array->namect);
00312
00313
00314
00315
00316
00317 if (strcmp(config_list, "*:*") == 0) {
00318 for (cur_rank = 0; cur_rank < cb_nodes; cur_rank++) {
00319 ranklist[cur_rank] = cur_rank;
00320 }
00321 ADIOI_Free(cur_procname);
00322 ADIOI_Free(CtvAccess(yylval));
00323 CtvAccess(yylval) = NULL;
00324 ADIOI_Free(used_procnames);
00325 return cb_nodes;
00326 }
00327
00328 while (cur_rank < cb_nodes) {
00329 token = cb_config_list_lex();
00330
00331 if (token == AGG_EOS) {
00332 ADIOI_Free(cur_procname);
00333 ADIOI_Free(CtvAccess(yylval));
00334 CtvAccess(yylval) = NULL;
00335 ADIOI_Free(used_procnames);
00336 return cur_rank;
00337 }
00338
00339 if (token != AGG_WILDCARD && token != AGG_STRING) {
00340
00341 FPRINTF(stderr, "error parsing config list\n");
00342 ADIOI_Free(cur_procname);
00343 ADIOI_Free(CtvAccess(yylval));
00344 CtvAccess(yylval) = NULL;
00345 ADIOI_Free(used_procnames);
00346 return cur_rank;
00347 }
00348
00349 if (token == AGG_WILDCARD) {
00350 cur_procname_p = NULL;
00351 }
00352 else {
00353
00354
00355 ADIOI_Strncpy(cur_procname, CtvAccess(yylval), MPI_MAX_INFO_VAL+1);
00356 cur_procname_p = cur_procname;
00357 }
00358
00359
00360 max_procs = get_max_procs(cb_nodes);
00361
00362 #ifdef CB_CONFIG_LIST_DEBUG
00363 if (token == AGG_WILDCARD) {
00364 FPRINTF(stderr, "looking for *:%d\n", max_procs);
00365 }
00366 else {
00367 FPRINTF(stderr, "looking for %s:%d\n", cur_procname, max_procs);
00368 }
00369 #endif
00370
00371
00372 match_procs(cur_procname_p, max_procs, procnames, used_procnames,
00373 nr_procnames, ranklist, cb_nodes, &cur_rank);
00374 }
00375 ADIOI_Free(cur_procname);
00376 ADIOI_Free(CtvAccess(yylval));
00377 CtvAccess(yylval) = NULL;
00378 ADIOI_Free(used_procnames);
00379 return cur_rank;
00380 }
00381
00382
00383
00384 int ADIOI_cb_copy_name_array(MPI_Comm comm,
00385 int keyval,
00386 void *extra,
00387 void *attr_in,
00388 void **attr_out,
00389 int *flag)
00390 {
00391 ADIO_cb_name_array array;
00392
00393 ADIOI_UNREFERENCED_ARG(comm);
00394 ADIOI_UNREFERENCED_ARG(keyval);
00395 ADIOI_UNREFERENCED_ARG(extra);
00396
00397 array = (ADIO_cb_name_array) attr_in;
00398 if (array != NULL) array->refct++;
00399
00400 *attr_out = attr_in;
00401 *flag = 1;
00402
00403 return MPI_SUCCESS;
00404 }
00405
00406
00407
00408 int ADIOI_cb_delete_name_array(MPI_Comm comm,
00409 int keyval,
00410 void *attr_val,
00411 void *extra)
00412 {
00413 ADIO_cb_name_array array;
00414
00415 ADIOI_UNREFERENCED_ARG(comm);
00416 ADIOI_UNREFERENCED_ARG(extra);
00417
00418 array = (ADIO_cb_name_array) attr_val;
00419 ADIOI_Assert(array != NULL);
00420 array->refct--;
00421
00422 if (array->refct <= 0) {
00423
00424
00425 if (array->namect) {
00426
00427
00428
00429 ADIOI_Free(array->names[0]);
00430 }
00431 if (array->names != NULL) ADIOI_Free(array->names);
00432 ADIOI_Free(array);
00433 }
00434 return MPI_SUCCESS;
00435 }
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455 static int match_procs(char *name,
00456 int max_per_proc,
00457 char *procnames[],
00458 char used_procnames[],
00459 int nr_procnames,
00460 int ranks[],
00461 int nr_ranks,
00462 int *nr_ranks_allocated)
00463 {
00464 int wildcard_proc, cur_proc, old_nr_allocated, ret;
00465
00466
00467 old_nr_allocated = *nr_ranks_allocated;
00468
00469 if (name == NULL) {
00470
00471
00472
00473 if (max_per_proc == 0) {
00474
00475 for (cur_proc = 0; cur_proc < nr_procnames; cur_proc++) {
00476 used_procnames[cur_proc] = 1;
00477 }
00478 return 0;
00479 }
00480
00481
00482
00483
00484
00485
00486
00487
00488 wildcard_proc = 0;
00489
00490 while (nr_ranks - *nr_ranks_allocated > 0) {
00491
00492 while ((wildcard_proc < nr_procnames) &&
00493 (used_procnames[wildcard_proc] != 0))
00494 {
00495 wildcard_proc++;
00496 }
00497
00498 if (wildcard_proc == nr_procnames) {
00499
00500 return *nr_ranks_allocated - old_nr_allocated;
00501 }
00502
00503 #ifdef CB_CONFIG_LIST_DEBUG
00504 FPRINTF(stderr, "performing wildcard match (*:%d) starting with %s (%d)\n",
00505 max_per_proc, procnames[wildcard_proc], wildcard_proc);
00506 #endif
00507
00508 cur_proc = wildcard_proc;
00509
00510 #ifdef CB_CONFIG_LIST_DEBUG
00511 FPRINTF(stderr, " assigning name %s (%d) to rank %d in mapping\n",
00512 procnames[cur_proc], cur_proc, *nr_ranks_allocated);
00513 #endif
00514
00515
00516
00517
00518
00519 ranks[*nr_ranks_allocated] = cur_proc;
00520 *nr_ranks_allocated = *nr_ranks_allocated + 1;
00521 cur_proc++;
00522
00523
00524
00525
00526
00527
00528 ret = match_this_proc(procnames[wildcard_proc], cur_proc,
00529 max_per_proc-1, procnames, used_procnames,
00530 nr_procnames,
00531 ranks, nr_ranks, *nr_ranks_allocated);
00532 if (ret > 0) *nr_ranks_allocated = *nr_ranks_allocated + ret;
00533
00534
00535
00536
00537 used_procnames[wildcard_proc] = 1;
00538 wildcard_proc++;
00539 }
00540 }
00541 else {
00542
00543 #ifdef CB_CONFIG_LIST_DEBUG
00544 FPRINTF(stderr, "performing name match (%s:%d)\n", name, max_per_proc);
00545 #endif
00546
00547 ret = match_this_proc(name, 0, max_per_proc, procnames, used_procnames,
00548 nr_procnames, ranks, nr_ranks,
00549 *nr_ranks_allocated);
00550 if (ret > 0) *nr_ranks_allocated = *nr_ranks_allocated + ret;
00551 }
00552 return *nr_ranks_allocated - old_nr_allocated;
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575 static int match_this_proc(char *name,
00576 int cur_proc,
00577 int max_matches,
00578 char *procnames[],
00579 char used_procnames[],
00580 int nr_procnames,
00581 int ranks[],
00582 int nr_ranks,
00583 int nr_ranks_allocated)
00584 {
00585 int ranks_remaining, nr_to_alloc, old_nr_allocated;
00586
00587 old_nr_allocated = nr_ranks_allocated;
00588
00589
00590 ranks_remaining = nr_ranks - nr_ranks_allocated;
00591 nr_to_alloc = (max_matches < ranks_remaining) ?
00592 max_matches : ranks_remaining;
00593
00594 while (nr_to_alloc > 0) {
00595 cur_proc = find_name(name, procnames, used_procnames, nr_procnames,
00596 cur_proc);
00597 if (cur_proc < 0) {
00598
00599 return nr_ranks_allocated - old_nr_allocated;
00600 }
00601
00602
00603 #ifdef CB_CONFIG_LIST_DEBUG
00604 FPRINTF(stderr, " assigning name %s (%d) to rank %d in mapping\n",
00605 procnames[cur_proc], cur_proc, nr_ranks_allocated);
00606 #endif
00607
00608 ranks[nr_ranks_allocated] = cur_proc;
00609 nr_ranks_allocated++;
00610 used_procnames[cur_proc] = 1;
00611
00612 cur_proc++;
00613 nr_to_alloc--;
00614 }
00615
00616
00617 while (cur_proc >= 0) {
00618 cur_proc = find_name(name, procnames, used_procnames, nr_procnames,
00619 cur_proc);
00620 if (cur_proc >= 0) {
00621 #ifdef CB_CONFIG_LIST_DEBUG
00622 FPRINTF(stderr, " taking name %s (%d) out of procnames\n",
00623 procnames[cur_proc], cur_proc);
00624 #endif
00625 used_procnames[cur_proc] = 1;
00626 cur_proc++;
00627 }
00628 }
00629 return nr_ranks_allocated - old_nr_allocated;
00630 }
00631
00632
00633
00634
00635
00636
00637
00638 static int find_name(char *name,
00639 char *procnames[],
00640 char used_procnames[],
00641 int nr_procnames,
00642 int start_ind)
00643 {
00644 int i;
00645
00646 for (i=start_ind; i < nr_procnames; i++) {
00647 if (!used_procnames[i] && !strcmp(name, procnames[i])) break;
00648 }
00649
00650 if (i < nr_procnames) return i;
00651 else return -1;
00652 }
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663 static int get_max_procs(int cb_nodes)
00664 {
00665 int token, max_procs = -1;
00666 char *errptr;
00667
00668 token = cb_config_list_lex();
00669
00670 switch(token) {
00671 case AGG_EOS:
00672 case AGG_COMMA:
00673 return 1;
00674 case AGG_COLON:
00675 token = cb_config_list_lex();
00676 if (token != AGG_WILDCARD && token != AGG_STRING) return -1;
00677 if (token == AGG_WILDCARD) max_procs = cb_nodes;
00678 else if (token == AGG_STRING) {
00679 max_procs = strtol(CtvAccess(yylval), &errptr, 10);
00680 if (*errptr != '\0') {
00681
00682 max_procs = 1;
00683 }
00684 }
00685
00686 token = cb_config_list_lex();
00687 if (token != AGG_COMMA && token != AGG_EOS) return -1;
00688
00689
00690 if (max_procs < 0) return -1;
00691 else return max_procs;
00692 }
00693 return -1;
00694 }
00695
00696
00697
00698
00699
00700
00701 #ifdef ROMIO_BGL
00702
00703
00704 #define COLON ':'
00705 #define COMMA ';'
00706 #define DELIMS ":;"
00707 #else
00708
00709 #define COLON ':'
00710 #define COMMA ','
00711 #define DELIMS ":,"
00712 #endif
00713
00714 static int cb_config_list_lex(void)
00715 {
00716 int slen;
00717
00718 if (*CtvAccess(token_ptr) == '\0') return AGG_EOS;
00719
00720 slen = (int)strcspn(CtvAccess(token_ptr), DELIMS);
00721
00722 if (*CtvAccess(token_ptr) == COLON) {
00723 CtvAccess(token_ptr)++;
00724 return AGG_COLON;
00725 }
00726 if (*CtvAccess(token_ptr) == COMMA) {
00727 CtvAccess(token_ptr)++;
00728 return AGG_COMMA;
00729 }
00730
00731 if (*CtvAccess(token_ptr) == '*') {
00732
00733 if (slen == 1) {
00734 CtvAccess(token_ptr)++;
00735 return AGG_WILDCARD;
00736 }
00737 else return AGG_ERROR;
00738 }
00739
00740
00741
00742
00743
00744
00745
00746
00747 ADIOI_Strncpy(CtvAccess(yylval), CtvAccess(token_ptr), slen);
00748 CtvAccess(yylval)[slen] = '\0';
00749 CtvAccess(token_ptr) += slen;
00750 return AGG_STRING;
00751 }