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