-: 0:Source:/home/MPI/testing/mpich2/mpich2/src/pmi/simple/simple_pmi.c
-: 0:Graph:simple_pmi.gcno
-: 0:Data:simple_pmi.gcda
-: 0:Runs:4381
-: 0:Programs:1376
-: 1:/* -*- Mode: C; c-basic-offset:4 ; -*- */
-: 2:/*
-: 3: * (C) 2001 by Argonne National Laboratory.
-: 4: * See COPYRIGHT in top-level directory.
-: 5: */
-: 6:
-: 7:/*********************** PMI implementation ********************************/
-: 8:/*
-: 9: * This file implements the client-side of the PMI interface.
-: 10: *
-: 11: * Note that the PMI client code must not print error messages (except
-: 12: * when an abort is required) because MPI error handling is based on
-: 13: * reporting error codes to which messages are attached.
-: 14: *
-: 15: * In v2, we should require a PMI client interface to use MPI error codes
-: 16: * to provide better integration with MPICH2.
-: 17: */
-: 18:/***************************************************************************/
-: 19:
-: 20:#include "pmiconf.h"
-: 21:
-: 22:#define PMI_VERSION 1
-: 23:#define PMI_SUBVERSION 1
-: 24:
-: 25:#include <stdio.h>
-: 26:#ifdef HAVE_UNISTD_H
-: 27:#include <unistd.h>
-: 28:#endif
-: 29:#ifdef HAVE_STDLIB_H
-: 30:#include <stdlib.h>
-: 31:#endif
-: 32:#ifdef HAVE_STRING_H
-: 33:#include <string.h>
-: 34:#endif
-: 35:#ifdef HAVE_STRINGS_H
-: 36:#include <strings.h>
-: 37:#endif
-: 38:#ifdef USE_PMI_PORT
-: 39:#ifndef MAXHOSTNAME
-: 40:#define MAXHOSTNAME 256
-: 41:#endif
-: 42:#endif
-: 43:/* This should be moved to pmiu for shutdown */
-: 44:#if defined(HAVE_SYS_SOCKET_H)
-: 45:#include <sys/socket.h>
-: 46:#endif
-: 47:
-: 48:#include "mpibase.h" /* Get ATTRIBUTE, some base functions */
-: 49:/* mpimem includes the definitions for MPIU_Snprintf, MPIU_Malloc, and
-: 50: MPIU_Free */
-: 51:#include "mpimem.h"
-: 52:
-: 53:/* Temporary debug definitions */
-: 54:#if 0
-: 55:#define DBG_PRINTF(args) printf args ; fflush(stdout)
-: 56:#else
-: 57:#define DBG_PRINTF(args)
-: 58:#endif
-: 59:
-: 60:#include "pmi.h"
-: 61:#include "simple_pmiutil.h"
-: 62:#include "mpi.h" /* to get MPI_MAX_PORT_NAME */
-: 63:
-: 64:/*
-: 65: These are global variable used *ONLY* in this file, and are hence
-: 66: declared static.
-: 67: */
-: 68:
-: 69:
-: 70:static int PMI_fd = -1;
-: 71:static int PMI_size = 1;
-: 72:static int PMI_rank = 0;
-: 73:
-: 74:/* Set PMI_initialized to 1 for singleton init but no process manager
-: 75: to help. Initialized to 2 for normal initialization. Initialized
-: 76: to values higher than 2 when singleton_init by a process manager.
-: 77: All values higher than 1 invlove a PM in some way.
-: 78:*/
-: 79:typedef enum { PMI_UNINITIALIZED = 0,
-: 80: SINGLETON_INIT_BUT_NO_PM = 1,
-: 81: NORMAL_INIT_WITH_PM,
-: 82: SINGLETON_INIT_WITH_PM } PMIState;
-: 83:static PMIState PMI_initialized = PMI_UNINITIALIZED;
-: 84:
-: 85:/* ALL GLOBAL VARIABLES MUST BE INITIALIZED TO AVOID POLLUTING THE
-: 86: LIBRARY WITH COMMON SYMBOLS */
-: 87:static int PMI_kvsname_max = 0;
-: 88:static int PMI_keylen_max = 0;
-: 89:static int PMI_vallen_max = 0;
-: 90:
-: 91:static int PMI_iter_next_idx = 0;
-: 92:static int PMI_debug = 0;
-: 93:static int PMI_debug_init = 0; /* Set this to true to debug the init
-: 94: handshakes */
-: 95:static int PMI_spawned = 0;
-: 96:
-: 97:/* Function prototypes for internal routines */
-: 98:static int PMII_getmaxes( int *kvsname_max, int *keylen_max, int *vallen_max );
-: 99:static int PMII_iter( const char *kvsname, const int idx, int *nextidx,
-: 100: char *key, int key_len, char *val, int val_len );
-: 101:static int PMII_Set_from_port( int, int );
-: 102:static int PMII_Connect_to_pm( char *, int );
-: 103:
-: 104:static int GetResponse( const char [], const char [], int );
-: 105:static int getPMIFD( int * );
-: 106:
-: 107:#ifdef USE_PMI_PORT
-: 108:static int PMII_singinit(void);
-: 109:static int PMI_totalview = 0;
-: 110:#endif
-: 111:static int PMIi_InitIfSingleton(void);
-: 112:static int accept_one_connection(int);
-: 113:static char cached_singinit_key[PMIU_MAXLINE];
-: 114:static char cached_singinit_val[PMIU_MAXLINE];
-: 115:static char singinit_kvsname[256];
-: 116:
-: 117:/******************************** Group functions *************************/
-: 118:
-: 119:int PMI_Init( int *spawned )
4381: 120:{
-: 121: char *p;
4381: 122: int notset = 1;
-: 123: int rc;
-: 124:
-: 125: /* FIXME: Why is setvbuf commented out? */
-: 126: /* FIXME: What if the output should be fully buffered (directed to file)?
-: 127: unbuffered (user explicitly set?) */
-: 128: /* setvbuf(stdout,0,_IONBF,0); */
4381: 129: setbuf(stdout,NULL);
-: 130: /* PMIU_printf( 1, "PMI_INIT\n" ); */
-: 131:
-: 132: /* Get the value of PMI_DEBUG from the environment if possible, since
-: 133: we may have set it to help debug the setup process */
4381: 134: p = getenv( "PMI_DEBUG" );
4381: 135: if (p) PMI_debug = atoi( p );
-: 136:
-: 137: /* Get the fd for PMI commands; if none, we're a singleton */
4381: 138: rc = getPMIFD(¬set);
4381: 139: if (rc) {
|
#####: 140: return rc;
-: 141: }
-: 142:
|
4381: 143: if ( PMI_fd == -1 ) {
-: 144: /* Singleton init: Process not started with mpiexec,
-: 145: so set size to 1, rank to 0 */
|
#####: 146: PMI_size = 1;
#####: 147: PMI_rank = 0;
#####: 148: *spawned = 0;
-: 149:
#####: 150: PMI_initialized = SINGLETON_INIT_BUT_NO_PM;
-: 151: /* 256 is picked as the minimum allowed length by the PMI servers */
#####: 152: PMI_kvsname_max = 256;
#####: 153: PMI_keylen_max = 256;
#####: 154: PMI_vallen_max = 256;
-: 155:
#####: 156: return( 0 );
-: 157: }
-: 158:
-: 159: /* If size, rank, and debug are not set from a communication port,
-: 160: use the environment */
|
4381: 161: if (notset) {
4381: 162: if ( ( p = getenv( "PMI_SIZE" ) ) )
4381: 163: PMI_size = atoi( p );
-: 164: else
|
#####: 165: PMI_size = 1;
-: 166:
|
4381: 167: if ( ( p = getenv( "PMI_RANK" ) ) ) {
4381: 168: PMI_rank = atoi( p );
-: 169: /* Let the util routine know the rank of this process for
-: 170: any messages (usually debugging or error) */
4381: 171: PMIU_Set_rank( PMI_rank );
-: 172: }
-: 173: else
|
#####: 174: PMI_rank = 0;
-: 175:
|
4381: 176: if ( ( p = getenv( "PMI_DEBUG" ) ) )
4381: 177: PMI_debug = atoi( p );
-: 178: else
|
#####: 179: PMI_debug = 0;
-: 180:
-: 181: /* Leave unchanged otherwise, which indicates that no value
-: 182: was set */
-: 183: }
-: 184:
-: 185:/* FIXME: Why does this depend on their being a port??? */
-: 186:/* FIXME: What is this for? */
-: 187:#ifdef USE_PMI_PORT
|
4381: 188: if ( ( p = getenv( "PMI_TOTALVIEW" ) ) )
4381: 189: PMI_totalview = atoi( p );
4381: 190: if ( PMI_totalview ) {
-: 191: char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE];
-: 192: /* FIXME: This should use a cmd/response rather than a expecting the
-: 193: server to set a value in this and only this case */
-: 194: /* FIXME: And it most ceratainly should not happen *before* the
-: 195: initialization handshake */
|
#####: 196: PMIU_readline( PMI_fd, buf, PMIU_MAXLINE );
#####: 197: PMIU_parse_keyvals( buf );
#####: 198: PMIU_getval( "cmd", cmd, PMIU_MAXLINE );
#####: 199: if ( strncmp( cmd, "tv_ready", PMIU_MAXLINE ) != 0 ) {
#####: 200: PMIU_printf( 1, "expecting cmd=tv_ready, got %s\n", buf );
#####: 201: return( PMI_FAIL );
-: 202: }
-: 203: }
-: 204:#endif
-: 205:
|
4381: 206: PMII_getmaxes( &PMI_kvsname_max, &PMI_keylen_max, &PMI_vallen_max );
-: 207:
-: 208: /* FIXME: This is something that the PM should tell the process,
-: 209: rather than deliver it through the environment */
4381: 210: if ( ( p = getenv( "PMI_SPAWNED" ) ) )
4381: 211: PMI_spawned = atoi( p );
-: 212: else
|
#####: 213: PMI_spawned = 0;
|
4381: 214: if (PMI_spawned)
406: 215: *spawned = 1;
-: 216: else
3975: 217: *spawned = 0;
-: 218:
4381: 219: if ( ! PMI_initialized )
4381: 220: PMI_initialized = NORMAL_INIT_WITH_PM;
-: 221:
4381: 222: return( 0 );
-: 223:}
-: 224:
-: 225:int PMI_Initialized( PMI_BOOL *initialized )
|
#####: 226:{
-: 227: /* Turn this into a logical value (1 or 0) . This allows us
-: 228: to use PMI_initialized to distinguish between initialized with
-: 229: an PMI service (e.g., via mpiexec) and the singleton init,
-: 230: which has no PMI service */
#####: 231: *initialized = PMI_initialized != 0 ? PMI_TRUE : PMI_FALSE;
#####: 232: return PMI_SUCCESS;
-: 233:}
-: 234:
-: 235:int PMI_Get_size( int *size )
|
4381: 236:{
4381: 237: if ( PMI_initialized )
4381: 238: *size = PMI_size;
-: 239: else
|
#####: 240: *size = 1;
|
4381: 241: return( 0 );
-: 242:}
-: 243:
-: 244:int PMI_Get_rank( int *rank )
4381: 245:{
4381: 246: if ( PMI_initialized )
4381: 247: *rank = PMI_rank;
-: 248: else
|
#####: 249: *rank = 0;
|
4381: 250: return( 0 );
-: 251:}
-: 252:
-: 253:/*
-: 254: * Get_universe_size is one of the routines that needs to communicate
-: 255: * with the process manager. If we started as a singleton init, then
-: 256: * we first need to connect to the process manager and acquire the
-: 257: * needed information.
-: 258: */
-: 259:int PMI_Get_universe_size( int *size)
5: 260:{
-: 261: int err;
-: 262: char size_c[PMIU_MAXLINE];
-: 263:
-: 264: /* Connect to the PM if we haven't already */
5: 265: if (PMIi_InitIfSingleton() != 0) return -1;
-: 266:
5: 267: if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) {
5: 268: err = GetResponse( "cmd=get_universe_size\n", "universe_size", 0 );
5: 269: if (err == PMI_SUCCESS) {
5: 270: PMIU_getval( "size", size_c, PMIU_MAXLINE );
5: 271: *size = atoi(size_c);
5: 272: return( PMI_SUCCESS );
-: 273: }
|
#####: 274: else return err;
-: 275: }
-: 276: else
#####: 277: *size = 1;
#####: 278: return( PMI_SUCCESS );
-: 279:}
-: 280:
-: 281:int PMI_Get_appnum( int *appnum )
|
4381: 282:{
-: 283: int err;
-: 284: char appnum_c[PMIU_MAXLINE];
-: 285:
4381: 286: if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) {
4381: 287: err = GetResponse( "cmd=get_appnum\n", "appnum", 0 );
4381: 288: if (err == PMI_SUCCESS) {
4381: 289: PMIU_getval( "appnum", appnum_c, PMIU_MAXLINE );
4381: 290: *appnum = atoi(appnum_c);
4381: 291: return( PMI_SUCCESS );
-: 292: }
|
#####: 293: else return err;
-: 294:
-: 295: }
-: 296: else
#####: 297: *appnum = -1;
-: 298:
#####: 299: return( PMI_SUCCESS );
-: 300:}
-: 301:
-: 302:int PMI_Barrier( void )
|
4463: 303:{
4463: 304: int err = PMI_SUCCESS;
-: 305:
4463: 306: if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) {
4463: 307: err = GetResponse( "cmd=barrier_in\n", "barrier_out", 0 );
-: 308: }
-: 309:
4463: 310: return err;
-: 311:}
-: 312:
-: 313:/* */
-: 314:static int clique_size=-2, *clique_ranks =0;
-: 315:
-: 316:/* pmiPrivateLocalRanks_<r> gets the local ranks for this process */
-: 317:int PMI_Get_clique_size( int *size )
|
#####: 318:{
-: 319:#if 1
-: 320: char buf[PMIU_MAXLINE];
-: 321: char pmi_kvsname[1024];
-: 322: int i, rc, err;
-: 323:
-: 324: /* As the server for the information on the */
#####: 325: if (clique_size == -2 && PMI_initialized > SINGLETON_INIT_BUT_NO_PM) {
#####: 326: PMI_KVS_Get_my_name( pmi_kvsname, sizeof(pmi_kvsname) );
#####: 327: rc = MPIU_Snprintf( buf, PMIU_MAXLINE,
-: 328: "cmd=get kvsname=%s key=pmiPrivateLocalRanks_%d\n",
-: 329: pmi_kvsname, PMI_rank );
#####: 330: if (rc < 0) return PMI_FAIL;
-: 331:
#####: 332: err = GetResponse( buf, "get_result", 0 );
#####: 333: if (err == PMI_SUCCESS) {
#####: 334: PMIU_getval( "rc", buf, PMIU_MAXLINE );
#####: 335: rc = atoi( buf );
#####: 336: if ( rc == 0 ) {
#####: 337: char *p = buf, *p0;
-: 338: /* Allocate clique_ranks and fill it in */
#####: 339: PMIU_getval( "value", buf, PMIU_MAXLINE );
-: 340: /* Count the number of ranks and allocate the space for them */
#####: 341: clique_size = 1;
#####: 342: while (*p) {
#####: 343: if (*p++ == ',') clique_size++;
-: 344: }
#####: 345: clique_ranks = (int *)MPIU_Malloc( clique_size * sizeof(int) );
-: 346: DBG_PRINTF( ("Clique_size = %d\n", clique_size) );
#####: 347: p0 = p = buf;
#####: 348: i = 0;
#####: 349: while (*p) {
#####: 350: while (*p && *p != ',') p++;
#####: 351: if (*p == ',') *p++ = 0;
#####: 352: clique_ranks[i++] = atoi(p0);
#####: 353: p0 = p;
-: 354: }
-: 355: }
-: 356: else {
-: 357: /* Default case (PM did not understand request) */
#####: 358: clique_size = 1;
-: 359: }
-: 360: }
-: 361: }
#####: 362: if (clique_size < 0) *size = 1;
#####: 363: else *size = clique_size;
-: 364:#else
-: 365: *size = 1;
-: 366:#endif
#####: 367: return PMI_SUCCESS;
-: 368:}
-: 369:
-: 370:int PMI_Get_clique_ranks( int ranks[], int length )
#####: 371:{
-: 372:#if 1
-: 373: int i;
#####: 374: if (length < 1)
#####: 375: return PMI_ERR_INVALID_ARG;
-: 376:
#####: 377: if (clique_size > 0 && clique_ranks) {
#####: 378: for (i=0; i<length && i<clique_size; i++)
#####: 379: ranks[i] = clique_ranks[i];
-: 380: }
-: 381: else
#####: 382: ranks[0] = PMI_rank;
#####: 383: return PMI_SUCCESS;
-: 384:#else
-: 385: if ( length < 1 )
-: 386: return PMI_ERR_INVALID_ARG;
-: 387: else
-: 388: return PMI_Get_rank( &ranks[0] );
-: 389:#endif
-: 390:}
-: 391:
-: 392:/* Inform the process manager that we're in finalize */
-: 393:int PMI_Finalize( void )
|
4374: 394:{
4374: 395: int err = PMI_SUCCESS;
-: 396:
4374: 397: if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) {
4374: 398: err = GetResponse( "cmd=finalize\n", "finalize_ack", 0 );
4374: 399: shutdown( PMI_fd, SHUT_RDWR );
4374: 400: close( PMI_fd );
-: 401: }
-: 402: /* Free any memory that we've allocated */
4374: 403: if (clique_ranks) MPIU_Free( clique_ranks );
-: 404:
4374: 405: return err;
-: 406:}
-: 407:
-: 408:int PMI_Abort(int exit_code, const char error_msg[])
7: 409:{
7: 410: PMIU_printf(1, "aborting job:\n%s\n", error_msg);
7: 411: MPIU_Exit(exit_code);
|
#####: 412: return -1;
-: 413:}
-: 414:
-: 415:/************************************* Keymap functions **********************/
-: 416:
-: 417:/*FIXME: need to return an error if the value of the kvs name returned is
-: 418: truncated because it is larger than length */
-: 419:/* FIXME: My name should be cached rather than re-acquired, as it is
-: 420: unchanging (after singleton init) */
-: 421:int PMI_KVS_Get_my_name( char kvsname[], int length )
|
8762: 422:{
-: 423: int err;
-: 424:
8762: 425: if (PMI_initialized == SINGLETON_INIT_BUT_NO_PM) {
-: 426: /* Return a dummy name */
-: 427: /* FIXME: We need to support a distinct kvsname for each
-: 428: process group */
|
#####: 429: MPIU_Snprintf( kvsname, length, "singinit_kvs_%d_0", (int)getpid() );
#####: 430: return 0;
-: 431: }
|
8762: 432: err = GetResponse( "cmd=get_my_kvsname\n", "my_kvsname", 0 );
8762: 433: if (err == PMI_SUCCESS) {
8762: 434: PMIU_getval( "kvsname", kvsname, length );
-: 435: }
8762: 436: return err;
-: 437:}
-: 438:
-: 439:int PMI_KVS_Get_name_length_max( int *maxlen )
4381: 440:{
4381: 441: if (maxlen == NULL)
|
#####: 442: return PMI_ERR_INVALID_ARG;
|
4381: 443: *maxlen = PMI_kvsname_max;
4381: 444: return PMI_SUCCESS;
-: 445:}
-: 446:
-: 447:int PMI_KVS_Get_key_length_max( int *maxlen )
3939: 448:{
3939: 449: if (maxlen == NULL)
|
#####: 450: return PMI_ERR_INVALID_ARG;
|
3939: 451: *maxlen = PMI_keylen_max;
3939: 452: return PMI_SUCCESS;
-: 453:}
-: 454:
-: 455:int PMI_KVS_Get_value_length_max( int *maxlen )
8238: 456:{
8238: 457: if (maxlen == NULL)
|
#####: 458: return PMI_ERR_INVALID_ARG;
|
8238: 459: *maxlen = PMI_vallen_max;
8238: 460: return PMI_SUCCESS;
-: 461:}
-: 462:
-: 463:/* We will use the default kvsname for both the kvs_domain_id and for the id */
-: 464:/* Hence the implementation of the following three functions */
-: 465:
-: 466:int PMI_Get_id_length_max( int *length )
24840: 467:{
24840: 468: if (length == NULL)
|
#####: 469: return PMI_ERR_INVALID_ARG;
|
24840: 470: *length = PMI_kvsname_max;
24840: 471: return PMI_SUCCESS;
-: 472:}
-: 473:
-: 474:int PMI_Get_id( char id_str[], int length )
4381: 475:{
4381: 476: int rc = PMI_KVS_Get_my_name( id_str, length );
4381: 477: return rc;
-: 478:}
-: 479:
-: 480:/* FIXME: What is this function? How is it defined and used? */
-: 481:int PMI_Get_kvs_domain_id( char id_str[], int length )
|
#####: 482:{
#####: 483: return PMI_KVS_Get_my_name( id_str, length );
-: 484:}
-: 485:
-: 486:/*FIXME: need to return an error if the value of the kvs name returned is
-: 487: truncated because it is larger than length */
-: 488:int PMI_KVS_Create( char kvsname[], int length )
#####: 489:{
#####: 490: int err = PMI_SUCCESS;
-: 491:
#####: 492: if (PMI_initialized == SINGLETON_INIT_BUT_NO_PM) {
-: 493: /* It is ok to pretend to *create* a kvs space */
#####: 494: return 0;
-: 495: }
-: 496:
#####: 497: err = GetResponse( "cmd=create_kvs\n", "newkvs", 0 );
#####: 498: if (err == PMI_SUCCESS) {
#####: 499: PMIU_getval( "kvsname", kvsname, length );
-: 500: }
#####: 501: return err;
-: 502:}
-: 503:
-: 504:int PMI_KVS_Destroy( const char kvsname[] )
#####: 505:{
-: 506: char buf[PMIU_MAXLINE];
#####: 507: int err = PMI_SUCCESS;
-: 508:
#####: 509: if (PMI_initialized == SINGLETON_INIT_BUT_NO_PM) {
#####: 510: return 0;
-: 511: }
-: 512:
-: 513: /* FIXME: Check for tempbuf too short */
#####: 514: MPIU_Snprintf( buf, PMIU_MAXLINE, "cmd=destroy_kvs kvsname=%s\n",
-: 515: kvsname );
#####: 516: err = GetResponse( buf, "kvs_destroyed", 1 );
#####: 517: return err;
-: 518:
-: 519:}
-: 520:
-: 521:int PMI_KVS_Put( const char kvsname[], const char key[], const char value[] )
|
4463: 522:{
-: 523: char buf[PMIU_MAXLINE];
4463: 524: int err = PMI_SUCCESS;
-: 525: int rc;
-: 526:
-: 527: /* This is a special hack to support singleton initialization */
4463: 528: if (PMI_initialized == SINGLETON_INIT_BUT_NO_PM) {
|
#####: 529: rc = MPIU_Strncpy(cached_singinit_key,key,PMI_keylen_max);
#####: 530: if (rc != 0) return PMI_FAIL;
#####: 531: rc = MPIU_Strncpy(cached_singinit_val,value,PMI_vallen_max);
#####: 532: if (rc != 0) return PMI_FAIL;
#####: 533: return 0;
-: 534: }
-: 535:
|
4463: 536: rc = MPIU_Snprintf( buf, PMIU_MAXLINE,
-: 537: "cmd=put kvsname=%s key=%s value=%s\n",
-: 538: kvsname, key, value);
4463: 539: if (rc < 0) return PMI_FAIL;
4463: 540: err = GetResponse( buf, "put_result", 1 );
4463: 541: return err;
-: 542:}
-: 543:
-: 544:int PMI_KVS_Commit( const char kvsname[] ATTRIBUTE((unused)))
4463: 545:{
-: 546: /* no-op in this implementation */
4463: 547: return( 0 );
-: 548:}
-: 549:
-: 550:/*FIXME: need to return an error if the value returned is truncated
-: 551: because it is larger than length */
-: 552:int PMI_KVS_Get( const char kvsname[], const char key[], char value[],
-: 553: int length)
13414: 554:{
-: 555: char buf[PMIU_MAXLINE];
13414: 556: int err = PMI_SUCCESS;
-: 557: int rc;
-: 558:
-: 559: /* Connect to the PM if we haven't already. This is needed in case
-: 560: we're doing an MPI_Comm_join or MPI_Comm_connect/accept from
-: 561: the singleton init case. This test is here because, in the way in
-: 562: which MPICH2 uses PMI, this is where the test needs to be. */
13414: 563: if (PMIi_InitIfSingleton() != 0) return -1;
-: 564:
13414: 565: rc = MPIU_Snprintf( buf, PMIU_MAXLINE, "cmd=get kvsname=%s key=%s\n",
-: 566: kvsname, key );
13414: 567: if (rc < 0) return PMI_FAIL;
-: 568:
13414: 569: err = GetResponse( buf, "get_result", 0 );
13414: 570: if (err == PMI_SUCCESS) {
13414: 571: PMIU_getval( "rc", buf, PMIU_MAXLINE );
13414: 572: rc = atoi( buf );
13414: 573: if ( rc == 0 ) {
13332: 574: PMIU_getval( "value", value, length );
13332: 575: return( 0 );
-: 576: }
-: 577: else {
82: 578: return( -1 );
-: 579: }
-: 580: }
-: 581:
|
#####: 582: return err;
-: 583:}
-: 584:
-: 585:int PMI_KVS_Iter_first(const char kvsname[], char key[], int key_len,
-: 586: char val[], int val_len)
#####: 587:{
-: 588: int rc;
-: 589:
#####: 590: rc = PMII_iter( kvsname, 0, &PMI_iter_next_idx, key, key_len, val, val_len );
#####: 591: return( rc );
-: 592:}
-: 593:
-: 594:int PMI_KVS_Iter_next(const char kvsname[], char key[], int key_len,
-: 595: char val[], int val_len)
#####: 596:{
-: 597: int rc;
-: 598:
#####: 599: rc = PMII_iter( kvsname, PMI_iter_next_idx, &PMI_iter_next_idx,
-: 600: key, key_len, val, val_len );
#####: 601: if ( rc == -2 )
#####: 602: PMI_iter_next_idx = 0;
#####: 603: return( rc );
-: 604:}
-: 605:
-: 606:/*************************** Name Publishing functions **********************/
-: 607:
-: 608:int PMI_Publish_name( const char service_name[], const char port[] )
|
4: 609:{
-: 610: char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE];
-: 611: int err;
-: 612:
4: 613: if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) {
4: 614: MPIU_Snprintf( cmd, PMIU_MAXLINE,
-: 615: "cmd=publish_name service=%s port=%s\n",
-: 616: service_name, port );
4: 617: err = GetResponse( cmd, "publish_result", 0 );
-: 618: /* FIXME: This should have used rc and msg */
4: 619: if (err == PMI_SUCCESS) {
4: 620: PMIU_getval( "info", buf, PMIU_MAXLINE );
4: 621: if ( strcmp(buf,"ok") != 0 ) {
|
#####: 622: PMIU_printf( 1, "publish failed; reason = %s\n", buf );
#####: 623: return( PMI_FAIL );
-: 624: }
-: 625: }
-: 626: }
-: 627: else
-: 628: {
#####: 629: PMIU_printf( 1, "PMI_Publish_name called before init\n" );
#####: 630: return( PMI_FAIL );
-: 631: }
-: 632:
|
4: 633: return( PMI_SUCCESS );
-: 634:}
-: 635:
-: 636:int PMI_Unpublish_name( const char service_name[] )
4: 637:{
-: 638: char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE];
4: 639: int err = PMI_SUCCESS;
-: 640:
4: 641: if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) {
4: 642: MPIU_Snprintf( cmd, PMIU_MAXLINE, "cmd=unpublish_name service=%s\n",
-: 643: service_name );
4: 644: err = GetResponse( cmd, "unpublish_result", 0 );
4: 645: if (err == PMI_SUCCESS) {
4: 646: PMIU_getval( "info", buf, PMIU_MAXLINE );
4: 647: if ( strcmp(buf,"ok") != 0 ) {
-: 648: /* FIXME: Do correct error reporting */
-: 649: /*
-: 650: PMIU_printf( 1, "unpublish failed; reason = %s\n", buf );
-: 651: */
1: 652: return( PMI_FAIL );
-: 653: }
-: 654: }
-: 655: }
-: 656: else
-: 657: {
|
#####: 658: PMIU_printf( 1, "PMI_Unpublish_name called before init\n" );
#####: 659: return( PMI_FAIL );
-: 660: }
-: 661:
|
3: 662: return( PMI_SUCCESS );
-: 663:}
-: 664:
-: 665:int PMI_Lookup_name( const char service_name[], char port[] )
31: 666:{
-: 667: char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE];
-: 668: int err;
-: 669:
31: 670: if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) {
31: 671: MPIU_Snprintf( cmd, PMIU_MAXLINE, "cmd=lookup_name service=%s\n",
-: 672: service_name );
31: 673: err = GetResponse( cmd, "lookup_result", 0 );
31: 674: if (err == PMI_SUCCESS) {
31: 675: PMIU_getval( "info", buf, PMIU_MAXLINE );
31: 676: if ( strcmp(buf,"ok") != 0 ) {
-: 677: /* FIXME: Do correct error reporting */
-: 678: /****
-: 679: PMIU_printf( 1, "lookup failed; reason = %s\n", buf );
-: 680: ****/
27: 681: return( PMI_FAIL );
-: 682: }
4: 683: PMIU_getval( "port", port, MPI_MAX_PORT_NAME );
-: 684: }
-: 685: }
-: 686: else
-: 687: {
|
#####: 688: PMIU_printf( 1, "PMI_Lookup_name called before init\n" );
#####: 689: return( PMI_FAIL );
-: 690: }
-: 691:
|
4: 692: return( PMI_SUCCESS );
-: 693:}
-: 694:
-: 695:
-: 696:/************************** Process Creation functions **********************/
-: 697:
-: 698:int PMI_Spawn_multiple(int count,
-: 699: const char * cmds[],
-: 700: const char ** argvs[],
-: 701: const int maxprocs[],
-: 702: const int info_keyval_sizes[],
-: 703: const PMI_keyval_t * info_keyval_vectors[],
-: 704: int preput_keyval_size,
-: 705: const PMI_keyval_t preput_keyval_vector[],
-: 706: int errors[])
357: 707:{
-: 708: int i,rc,argcnt,spawncnt,total_num_processes,num_errcodes_found;
-: 709: char buf[PMIU_MAXLINE], tempbuf[PMIU_MAXLINE], cmd[PMIU_MAXLINE];
-: 710: char *lead, *lag;
-: 711:
-: 712: /* Connect to the PM if we haven't already */
357: 713: if (PMIi_InitIfSingleton() != 0) return -1;
-: 714:
357: 715: total_num_processes = 0;
-: 716:
718: 717: for (spawncnt=0; spawncnt < count; spawncnt++)
-: 718: {
361: 719: total_num_processes += maxprocs[spawncnt];
-: 720:
361: 721: rc = MPIU_Snprintf(buf, PMIU_MAXLINE,
-: 722: "mcmd=spawn\nnprocs=%d\nexecname=%s\n",
-: 723: maxprocs[spawncnt], cmds[spawncnt] );
361: 724: if (rc < 0) {
|
#####: 725: return PMI_FAIL;
-: 726: }
-: 727:
|
361: 728: rc = MPIU_Snprintf(tempbuf, PMIU_MAXLINE,
-: 729: "totspawns=%d\nspawnssofar=%d\n",
-: 730: count, spawncnt+1);
-: 731:
361: 732: if (rc < 0) {
|
#####: 733: return PMI_FAIL;
-: 734: }
|
361: 735: rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE);
361: 736: if (rc != 0) {
|
#####: 737: return PMI_FAIL;
-: 738: }
-: 739:
|
361: 740: argcnt = 0;
361: 741: if ((argvs != NULL) && (argvs[spawncnt] != NULL)) {
736: 742: for (i=0; argvs[spawncnt][i] != NULL; i++)
-: 743: {
-: 744: /* FIXME (protocol design flaw): command line arguments
-: 745: may contain both = and <space> (and even tab!).
-: 746: */
-: 747: /* Note that part of this fixme was really a design error -
-: 748: because this uses the mcmd form, the data can be
-: 749: sent in multiple writelines. This code now takes
-: 750: advantage of that. Note also that a correct parser
-: 751: of the commands will permit any character other than a
-: 752: new line in the argument, since the form is
-: 753: argn=<any nonnewline><newline> */
653: 754: rc = MPIU_Snprintf(tempbuf,PMIU_MAXLINE,"arg%d=%s\n",
-: 755: i+1,argvs[spawncnt][i]);
653: 756: if (rc < 0) {
|
#####: 757: return PMI_FAIL;
-: 758: }
|
653: 759: rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE);
653: 760: if (rc != 0) {
|
#####: 761: return PMI_FAIL;
-: 762: }
|
653: 763: argcnt++;
653: 764: rc = PMIU_writeline( PMI_fd, buf );
653: 765: buf[0] = 0;
-: 766:
-: 767: }
-: 768: }
361: 769: rc = MPIU_Snprintf(tempbuf,PMIU_MAXLINE,"argcnt=%d\n",argcnt);
361: 770: if (rc < 0) {
|
#####: 771: return PMI_FAIL;
-: 772: }
|
361: 773: rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE);
361: 774: if (rc != 0) {
|
#####: 775: return PMI_FAIL;
-: 776: }
-: 777:
|
361: 778: rc = MPIU_Snprintf(tempbuf,PMIU_MAXLINE,"preput_num=%d\n",
-: 779: preput_keyval_size);
361: 780: if (rc < 0) {
|
#####: 781: return PMI_FAIL;
-: 782: }
-: 783:
|
361: 784: rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE);
361: 785: if (rc != 0) {
|
#####: 786: return PMI_FAIL;
-: 787: }
|
722: 788: for (i=0; i < preput_keyval_size; i++) {
361: 789: rc = MPIU_Snprintf(tempbuf,PMIU_MAXLINE,"preput_key_%d=%s\n",
-: 790: i,preput_keyval_vector[i].key);
361: 791: if (rc < 0) {
|
#####: 792: return PMI_FAIL;
-: 793: }
|
361: 794: rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE);
361: 795: if (rc != 0) {
|
#####: 796: return PMI_FAIL;
-: 797: }
|
361: 798: rc = MPIU_Snprintf(tempbuf,PMIU_MAXLINE,"preput_val_%d=%s\n",
-: 799: i,preput_keyval_vector[i].val);
361: 800: if (rc < 0) {
|
#####: 801: return PMI_FAIL;
-: 802: }
|
361: 803: rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE);
361: 804: if (rc != 0) {
|
#####: 805: return PMI_FAIL;
-: 806: }
-: 807: }
|
361: 808: rc = MPIU_Snprintf(tempbuf,PMIU_MAXLINE,"info_num=%d\n",
-: 809: info_keyval_sizes[spawncnt]);
361: 810: if (rc < 0) {
|
#####: 811: return PMI_FAIL;
-: 812: }
|
361: 813: rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE);
361: 814: if (rc != 0) {
|
#####: 815: return PMI_FAIL;
-: 816: }
|
373: 817: for (i=0; i < info_keyval_sizes[spawncnt]; i++)
-: 818: {
12: 819: rc = MPIU_Snprintf(tempbuf,PMIU_MAXLINE,"info_key_%d=%s\n",
-: 820: i,info_keyval_vectors[spawncnt][i].key);
12: 821: if (rc < 0) {
|
#####: 822: return PMI_FAIL;
-: 823: }
|
12: 824: rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE);
12: 825: if (rc != 0) {
|
#####: 826: return PMI_FAIL;
-: 827: }
|
12: 828: rc = MPIU_Snprintf(tempbuf,PMIU_MAXLINE,"info_val_%d=%s\n",
-: 829: i,info_keyval_vectors[spawncnt][i].val);
12: 830: if (rc < 0) {
|
#####: 831: return PMI_FAIL;
-: 832: }
|
12: 833: rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE);
12: 834: if (rc != 0) {
|
#####: 835: return PMI_FAIL;
-: 836: }
-: 837: }
-: 838:
|
361: 839: rc = MPIU_Strnapp(buf, "endcmd\n", PMIU_MAXLINE);
361: 840: if (rc != 0) {
|
#####: 841: return PMI_FAIL;
-: 842: }
|
361: 843: PMIU_writeline( PMI_fd, buf );
-: 844: }
-: 845:
357: 846: PMIU_readline( PMI_fd, buf, PMIU_MAXLINE );
357: 847: PMIU_parse_keyvals( buf );
357: 848: PMIU_getval( "cmd", cmd, PMIU_MAXLINE );
357: 849: if ( strncmp( cmd, "spawn_result", PMIU_MAXLINE ) != 0 ) {
|
#####: 850: PMIU_printf( 1, "got unexpected response to spawn :%s:\n", buf );
#####: 851: return( -1 );
-: 852: }
-: 853: else {
|
357: 854: PMIU_getval( "rc", buf, PMIU_MAXLINE );
357: 855: rc = atoi( buf );
357: 856: if ( rc != 0 ) {
-: 857: /****
-: 858: PMIU_getval( "status", tempbuf, PMIU_MAXLINE );
-: 859: PMIU_printf( 1, "pmi_spawn_mult failed; status: %s\n",tempbuf);
-: 860: ****/
|
#####: 861: return( -1 );
-: 862: }
-: 863: }
-: 864:
|
357: 865: PMIU_Assert(errors != NULL);
357: 866: if (PMIU_getval( "errcodes", tempbuf, PMIU_MAXLINE )) {
357: 867: num_errcodes_found = 0;
357: 868: lag = &tempbuf[0];
-: 869: do {
406: 870: lead = strchr(lag, ',');
406: 871: if (lead) *lead = '\0';
406: 872: errors[num_errcodes_found++] = atoi(lag);
406: 873: lag = lead + 1; /* move past the null char */
406: 874: PMIU_Assert(num_errcodes_found <= total_num_processes);
406: 875: } while (lead != NULL);
357: 876: PMIU_Assert(num_errcodes_found == total_num_processes);
-: 877: }
-: 878: else {
-: 879: /* gforker doesn't return errcodes, so we'll just pretend that means
-: 880: that it was going to send all `0's. */
|
#####: 881: for (i = 0; i < total_num_processes; ++i) {
#####: 882: errors[i] = 0;
-: 883: }
-: 884: }
-: 885:
|
357: 886: return( 0 );
-: 887:}
-: 888:
-: 889:/***************** Internal routines not part of PMI interface ***************/
-: 890:
-: 891:/* get a keyval pair by specific index */
-: 892:
-: 893:static int PMII_iter( const char *kvsname, const int idx, int *next_idx,
-: 894: char *key, int key_len, char *val, int val_len)
|
#####: 895:{
-: 896: char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE];
-: 897: int rc, err;
-: 898:
-: 899: /* FIXME: Check for tempbuf too short */
#####: 900: rc = MPIU_Snprintf( buf, PMIU_MAXLINE, "cmd=getbyidx kvsname=%s idx=%d\n",
-: 901: kvsname, idx );
#####: 902: if (rc < 0) {
#####: 903: return PMI_FAIL;
-: 904: }
#####: 905: err = GetResponse( cmd, "getbyidx_results", 0 );
#####: 906: if (err == PMI_SUCCESS) {
#####: 907: PMIU_getval( "rc", buf, PMIU_MAXLINE );
-: 908: rc = atoi( buf );
#####: 909: if ( rc == 0 ) {
#####: 910: PMIU_getval( "nextidx", buf, PMIU_MAXLINE );
#####: 911: *next_idx = atoi( buf );
#####: 912: PMIU_getval( "key", key, key_len );
#####: 913: PMIU_getval( "val", val, val_len );
#####: 914: return( PMI_SUCCESS );
-: 915: }
-: 916: else {
#####: 917: PMIU_getval( "reason", buf, PMIU_MAXLINE );
#####: 918: if ( strncmp( buf, "no_more_keyvals", PMIU_MAXLINE ) == 0 ) {
#####: 919: key[0] = '\0';
#####: 920: return( PMI_SUCCESS );
-: 921: }
-: 922: else {
#####: 923: PMIU_printf( 1, "iter failed; reason = %s\n", buf );
#####: 924: return( PMI_FAIL );
-: 925: }
-: 926: }
-: 927: }
#####: 928: return err;
-: 929:}
-: 930:
-: 931:/* to get all maxes in one message */
-: 932:/* FIXME: This mixes init with get maxes */
-: 933:static int PMII_getmaxes( int *kvsname_max, int *keylen_max, int *vallen_max )
|
4381: 934:{
-: 935: char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE], errmsg[PMIU_MAXLINE];
-: 936: int err, rc;
-: 937:
4381: 938: rc = MPIU_Snprintf( buf, PMIU_MAXLINE,
-: 939: "cmd=init pmi_version=%d pmi_subversion=%d\n",
-: 940: PMI_VERSION, PMI_SUBVERSION );
4381: 941: if (rc < 0) {
|
#####: 942: return PMI_FAIL;
-: 943: }
-: 944:
|
4381: 945: rc = PMIU_writeline( PMI_fd, buf );
4381: 946: if (rc != 0) {
|
#####: 947: PMIU_printf( 1, "Unable to write to PMI_fd\n" );
#####: 948: return PMI_FAIL;
-: 949: }
|
4381: 950: buf[0] = 0; /* Ensure buffer is empty if read fails */
4381: 951: err = PMIU_readline( PMI_fd, buf, PMIU_MAXLINE );
4381: 952: if (err < 0) {
|
#####: 953: PMIU_printf( 1, "Error reading initack on %d\n", PMI_fd );
#####: 954: perror( "Error on readline:" );
#####: 955: PMI_Abort(-1, "Above error when reading after init" );
-: 956: }
|
4381: 957: PMIU_parse_keyvals( buf );
4381: 958: cmd[0] = 0;
4381: 959: PMIU_getval( "cmd", cmd, PMIU_MAXLINE );
4381: 960: if ( strncmp( cmd, "response_to_init", PMIU_MAXLINE ) != 0 ) {
|
#####: 961: MPIU_Snprintf(errmsg, PMIU_MAXLINE,
-: 962: "got unexpected response to init :%s: (full line = %s)",
-: 963: cmd, buf );
#####: 964: PMI_Abort( -1, errmsg );
-: 965: }
-: 966: else {
-: 967: char buf1[PMIU_MAXLINE];
|
4381: 968: PMIU_getval( "rc", buf, PMIU_MAXLINE );
4381: 969: if ( strncmp( buf, "0", PMIU_MAXLINE ) != 0 ) {
|
#####: 970: PMIU_getval( "pmi_version", buf, PMIU_MAXLINE );
#####: 971: PMIU_getval( "pmi_subversion", buf1, PMIU_MAXLINE );
#####: 972: MPIU_Snprintf(errmsg, PMIU_MAXLINE,
-: 973: "pmi_version mismatch; client=%d.%d mgr=%s.%s",
-: 974: PMI_VERSION, PMI_SUBVERSION, buf, buf1 );
#####: 975: PMI_Abort( -1, errmsg );
-: 976: }
-: 977: }
|
4381: 978: err = GetResponse( "cmd=get_maxes\n", "maxes", 0 );
4381: 979: if (err == PMI_SUCCESS) {
4381: 980: PMIU_getval( "kvsname_max", buf, PMIU_MAXLINE );
4381: 981: *kvsname_max = atoi( buf );
4381: 982: PMIU_getval( "keylen_max", buf, PMIU_MAXLINE );
4381: 983: *keylen_max = atoi( buf );
4381: 984: PMIU_getval( "vallen_max", buf, PMIU_MAXLINE );
4381: 985: *vallen_max = atoi( buf );
-: 986: }
4381: 987: return err;
-: 988:}
-: 989:
-: 990:/* ----------------------------------------------------------------------- */
-: 991:/*
-: 992: * This function is used to request information from the server and check
-: 993: * that the response uses the expected command name. On a successful
-: 994: * return from this routine, additional PMIU_getval calls may be used
-: 995: * to access information about the returned value.
-: 996: *
-: 997: * If checkRc is true, this routine also checks that the rc value returned
-: 998: * was 0. If not, it uses the "msg" value to report on the reason for
-: 999: * the failure.
-: 1000: */
-: 1001:static int GetResponse( const char request[], const char expectedCmd[],
-: 1002: int checkRc )
44282: 1003:{
-: 1004: int err, n;
-: 1005: char *p;
-: 1006: char recvbuf[PMIU_MAXLINE];
-: 1007: char cmdName[PMIU_MAXLINE];
-: 1008:
-: 1009: /* FIXME: This is an example of an incorrect fix - writeline can change
-: 1010: the second argument in some cases, and that will break the const'ness
-: 1011: of request. Instead, writeline should take a const item and return
-: 1012: an error in the case in which it currently truncates the data. */
44282: 1013: err = PMIU_writeline( PMI_fd, (char *)request );
44282: 1014: if (err) {
|
#####: 1015: return err;
-: 1016: }
|
44282: 1017: n = PMIU_readline( PMI_fd, recvbuf, sizeof(recvbuf) );
44282: 1018: if (n <= 0) {
|
#####: 1019: PMIU_printf( 1, "readline failed\n" );
#####: 1020: return PMI_FAIL;
-: 1021: }
|
44282: 1022: err = PMIU_parse_keyvals( recvbuf );
44282: 1023: if (err) {
|
#####: 1024: PMIU_printf( 1, "parse_kevals failed %d\n", err );
#####: 1025: return err;
-: 1026: }
|
44282: 1027: p = PMIU_getval( "cmd", cmdName, sizeof(cmdName) );
44282: 1028: if (!p) {
|
#####: 1029: PMIU_printf( 1, "getval cmd failed\n" );
#####: 1030: return PMI_FAIL;
-: 1031: }
|
44282: 1032: if (strcmp( expectedCmd, cmdName ) != 0) {
|
#####: 1033: PMIU_printf( 1, "expecting cmd=%s, got %s\n", expectedCmd, cmdName );
#####: 1034: return PMI_FAIL;
-: 1035: }
|
44282: 1036: if (checkRc) {
4463: 1037: p = PMIU_getval( "rc", cmdName, PMIU_MAXLINE );
4463: 1038: if ( p && strcmp(cmdName,"0") != 0 ) {
|
#####: 1039: PMIU_getval( "msg", cmdName, PMIU_MAXLINE );
#####: 1040: PMIU_printf( 1, "Command %s failed, reason='%s'\n",
-: 1041: request, cmdName );
#####: 1042: return PMI_FAIL;
-: 1043: }
-: 1044: }
-: 1045:
|
44282: 1046: return err;
-: 1047:}
-: 1048:/* ----------------------------------------------------------------------- */
-: 1049:
-: 1050:
-: 1051:#ifdef USE_PMI_PORT
-: 1052:/*
-: 1053: * This code allows a program to contact a host/port for the PMI socket.
-: 1054: */
-: 1055:#include <errno.h>
-: 1056:#if defined(HAVE_SYS_TYPES_H)
-: 1057:#include <sys/types.h>
-: 1058:#endif
-: 1059:#include <sys/param.h>
-: 1060:#include <sys/socket.h>
-: 1061:
-: 1062:/* sockaddr_in (Internet) */
-: 1063:#include <netinet/in.h>
-: 1064:/* TCP_NODELAY */
-: 1065:#include <netinet/tcp.h>
-: 1066:
-: 1067:/* sockaddr_un (Unix) */
-: 1068:#include <sys/un.h>
-: 1069:
-: 1070:/* defs of gethostbyname */
-: 1071:#include <netdb.h>
-: 1072:
-: 1073:/* fcntl, F_GET/SETFL */
-: 1074:#include <fcntl.h>
-: 1075:
-: 1076:/* This is really IP!? */
-: 1077:#ifndef TCP
-: 1078:#define TCP 0
-: 1079:#endif
-: 1080:
-: 1081:/* stub for connecting to a specified host/port instead of using a
-: 1082: specified fd inherited from a parent process */
-: 1083:static int PMII_Connect_to_pm( char *hostname, int portnum )
4381: 1084:{
-: 1085: struct hostent *hp;
-: 1086: struct sockaddr_in sa;
-: 1087: int fd;
4381: 1088: int optval = 1;
4381: 1089: int q_wait = 1;
-: 1090:
4381: 1091: hp = gethostbyname( hostname );
4381: 1092: if (!hp) {
|
#####: 1093: PMIU_printf( 1, "Unable to get host entry for %s\n", hostname );
#####: 1094: return -1;
-: 1095: }
-: 1096:
|
4381: 1097: memset( (void *)&sa, 0, sizeof(sa) );
-: 1098: /* POSIX might define h_addr_list only and node define h_addr */
-: 1099:#ifdef HAVE_H_ADDR_LIST
4381: 1100: memcpy( (void *)&sa.sin_addr, (void *)hp->h_addr_list[0], hp->h_length);
-: 1101:#else
-: 1102: memcpy( (void *)&sa.sin_addr, (void *)hp->h_addr, hp->h_length);
-: 1103:#endif
4381: 1104: sa.sin_family = hp->h_addrtype;
4381: 1105: sa.sin_port = htons( (unsigned short) portnum );
-: 1106:
4381: 1107: fd = socket( AF_INET, SOCK_STREAM, TCP );
4381: 1108: if (fd < 0) {
|
#####: 1109: PMIU_printf( 1, "Unable to get AF_INET socket\n" );
#####: 1110: return -1;
-: 1111: }
-: 1112:
|
4381: 1113: if (setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
-: 1114: (char *)&optval, sizeof(optval) )) {
|
#####: 1115: perror( "Error calling setsockopt:" );
-: 1116: }
-: 1117:
-: 1118: /* We wait here for the connection to succeed */
|
4381: 1119: if (connect( fd, (struct sockaddr *)&sa, sizeof(sa) ) < 0) {
|
#####: 1120: switch (errno) {
-: 1121: case ECONNREFUSED:
#####: 1122: PMIU_printf( 1, "connect failed with connection refused\n" );
-: 1123: /* (close socket, get new socket, try again) */
#####: 1124: if (q_wait)
#####: 1125: close(fd);
#####: 1126: return -1;
-: 1127:
-: 1128: case EINPROGRESS: /* (nonblocking) - select for writing. */
-: 1129: break;
-: 1130:
-: 1131: case EISCONN: /* (already connected) */
-: 1132: break;
-: 1133:
-: 1134: case ETIMEDOUT: /* timed out */
#####: 1135: PMIU_printf( 1, "connect failed with timeout\n" );
#####: 1136: return -1;
-: 1137:
-: 1138: default:
#####: 1139: PMIU_printf( 1, "connect failed with errno %d\n", errno );
#####: 1140: return -1;
-: 1141: }
-: 1142: }
-: 1143:
|
4381: 1144: return fd;
-: 1145:}
-: 1146:
-: 1147:static int PMII_Set_from_port( int fd, int id )
|
#####: 1148:{
-: 1149: char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE];
-: 1150: int err, rc;
-: 1151:
-: 1152: /* We start by sending a startup message to the server */
-: 1153:
#####: 1154: if (PMI_debug) {
#####: 1155: PMIU_printf( 1, "Writing initack to destination fd %d\n", fd );
-: 1156: }
-: 1157: /* Handshake and initialize from a port */
-: 1158:
#####: 1159: rc = MPIU_Snprintf( buf, PMIU_MAXLINE, "cmd=initack pmiid=%d\n", id );
#####: 1160: if (rc < 0) {
#####: 1161: return PMI_FAIL;
-: 1162: }
#####: 1163: PMIU_printf( PMI_debug, "writing on fd %d line :%s:\n", fd, buf );
#####: 1164: err = PMIU_writeline( fd, buf );
#####: 1165: if (err) {
#####: 1166: PMIU_printf( 1, "Error in writeline initack\n" );
#####: 1167: return -1;
-: 1168: }
-: 1169:
-: 1170: /* cmd=initack */
#####: 1171: buf[0] = 0;
#####: 1172: PMIU_printf( PMI_debug, "reading initack\n" );
#####: 1173: err = PMIU_readline( fd, buf, PMIU_MAXLINE );
#####: 1174: if (err < 0) {
#####: 1175: PMIU_printf( 1, "Error reading initack on %d\n", fd );
#####: 1176: perror( "Error on readline:" );
#####: 1177: return -1;
-: 1178: }
#####: 1179: PMIU_parse_keyvals( buf );
#####: 1180: PMIU_getval( "cmd", cmd, PMIU_MAXLINE );
#####: 1181: if ( strcmp( cmd, "initack" ) ) {
#####: 1182: PMIU_printf( 1, "got unexpected input %s\n", buf );
#####: 1183: return -1;
-: 1184: }
-: 1185:
-: 1186: /* Read, in order, size, rank, and debug. Eventually, we'll want
-: 1187: the handshake to include a version number */
-: 1188:
-: 1189: /* size */
#####: 1190: PMIU_printf( PMI_debug, "reading size\n" );
#####: 1191: err = PMIU_readline( fd, buf, PMIU_MAXLINE );
#####: 1192: if (err < 0) {
#####: 1193: PMIU_printf( 1, "Error reading size on %d\n", fd );
#####: 1194: perror( "Error on readline:" );
#####: 1195: return -1;
-: 1196: }
#####: 1197: PMIU_parse_keyvals( buf );
#####: 1198: PMIU_getval( "cmd", cmd, PMIU_MAXLINE );
#####: 1199: if ( strcmp(cmd,"set")) {
#####: 1200: PMIU_printf( 1, "got unexpected command %s in %s\n", cmd, buf );
#####: 1201: return -1;
-: 1202: }
-: 1203: /* cmd=set size=n */
#####: 1204: PMIU_getval( "size", cmd, PMIU_MAXLINE );
#####: 1205: PMI_size = atoi(cmd);
-: 1206:
-: 1207: /* rank */
#####: 1208: PMIU_printf( PMI_debug, "reading rank\n" );
#####: 1209: err = PMIU_readline( fd, buf, PMIU_MAXLINE );
#####: 1210: if (err < 0) {
#####: 1211: PMIU_printf( 1, "Error reading rank on %d\n", fd );
#####: 1212: perror( "Error on readline:" );
#####: 1213: return -1;
-: 1214: }
#####: 1215: PMIU_parse_keyvals( buf );
#####: 1216: PMIU_getval( "cmd", cmd, PMIU_MAXLINE );
#####: 1217: if ( strcmp(cmd,"set")) {
#####: 1218: PMIU_printf( 1, "got unexpected command %s in %s\n", cmd, buf );
#####: 1219: return -1;
-: 1220: }
-: 1221: /* cmd=set rank=n */
#####: 1222: PMIU_getval( "rank", cmd, PMIU_MAXLINE );
#####: 1223: PMI_rank = atoi(cmd);
#####: 1224: PMIU_Set_rank( PMI_rank );
-: 1225:
-: 1226: /* debug flag */
#####: 1227: err = PMIU_readline( fd, buf, PMIU_MAXLINE );
#####: 1228: if (err < 0) {
#####: 1229: PMIU_printf( 1, "Error reading debug on %d\n", fd );
#####: 1230: return -1;
-: 1231: }
#####: 1232: PMIU_parse_keyvals( buf );
#####: 1233: PMIU_getval( "cmd", cmd, PMIU_MAXLINE );
#####: 1234: if ( strcmp(cmd,"set")) {
#####: 1235: PMIU_printf( 1, "got unexpected command %s in %s\n", cmd, buf );
#####: 1236: return -1;
-: 1237: }
-: 1238: /* cmd=set debug=n */
#####: 1239: PMIU_getval( "debug", cmd, PMIU_MAXLINE );
#####: 1240: PMI_debug = atoi(cmd);
-: 1241:
#####: 1242: if (PMI_debug) {
-: 1243: DBG_PRINTF( ("end of handshake, rank = %d, size = %d\n",
-: 1244: PMI_rank, PMI_size ));
-: 1245: DBG_PRINTF( ("Completed init\n" ) );
-: 1246: }
-: 1247:
#####: 1248: return 0;
-: 1249:}
-: 1250:
-: 1251:/* ------------------------------------------------------------------------- */
-: 1252:/*
-: 1253: * Singleton Init.
-: 1254: *
-: 1255: * MPI-2 allows processes to become MPI processes and then make MPI calls,
-: 1256: * such as MPI_Comm_spawn, that require a process manager (this is different
-: 1257: * than the much simpler case of allowing MPI programs to run with an
-: 1258: * MPI_COMM_WORLD of size 1 without an mpiexec or process manager).
-: 1259: *
-: 1260: * The process starts when either the client or the process manager contacts
-: 1261: * the other. If the client starts, it sends a singinit command and
-: 1262: * waits for the server to respond with its own singinit command.
-: 1263: * If the server start, it send a singinit command and waits for the
-: 1264: * client to respond with its own singinit command
-: 1265: *
-: 1266: * client sends singinit with these required values
-: 1267: * pmi_version=<value of PMI_VERSION>
-: 1268: * pmi_subversion=<value of PMI_SUBVERSION>
-: 1269: *
-: 1270: * and these optional values
-: 1271: * stdio=[yes|no]
-: 1272: * authtype=[none|shared|<other-to-be-defined>]
-: 1273: * authstring=<string>
-: 1274: *
-: 1275: * server sends singinit with the same required and optional values as
-: 1276: * above.
-: 1277: *
-: 1278: * At this point, the protocol is now the same in both cases, and has the
-: 1279: * following components:
-: 1280: *
-: 1281: * server sends singinit_info with these required fields
-: 1282: * versionok=[yes|no]
-: 1283: * stdio=[yes|no]
-: 1284: * kvsname=<string>
-: 1285: *
-: 1286: * The client then issues the init command (see PMII_getmaxes)
-: 1287: *
-: 1288: * cmd=init pmi_version=<val> pmi_subversion=<val>
-: 1289: *
-: 1290: * and expects to receive a
-: 1291: *
-: 1292: * cmd=response_to_init rc=0 pmi_version=<val> pmi_subversion=<val>
-: 1293: *
-: 1294: * (This is the usual init sequence).
-: 1295: *
-: 1296: */
-: 1297:/* ------------------------------------------------------------------------- */
-: 1298:/* This is a special routine used to re-initialize PMI when it is in
-: 1299: the singleton init case. That is, the executable was started without
-: 1300: mpiexec, and PMI_Init returned as if there was only one process.
-: 1301:
-: 1302: Note that PMI routines should not call PMII_singinit; they should
-: 1303: call PMIi_InitIfSingleton(), which both connects to the process mangager
-: 1304: and sets up the initial KVS connection entry.
-: 1305:*/
-: 1306:
-: 1307:static int PMII_singinit(void)
#####: 1308:{
-: 1309: int pid, rc;
-: 1310: int singinit_listen_sock, stdin_sock, stdout_sock, stderr_sock;
-: 1311: const char *newargv[8];
-: 1312: char charpid[8], port_c[8];
-: 1313: struct sockaddr_in sin;
-: 1314: socklen_t len;
-: 1315:
-: 1316: /* Create a socket on which to allow an mpiexec to connect back to
-: 1317: us */
#####: 1318: sin.sin_family = AF_INET;
#####: 1319: sin.sin_addr.s_addr = INADDR_ANY;
#####: 1320: sin.sin_port = htons(0); /* anonymous port */
#####: 1321: singinit_listen_sock = socket(AF_INET, SOCK_STREAM, 0);
#####: 1322: rc = bind(singinit_listen_sock, (struct sockaddr *)&sin ,sizeof(sin));
#####: 1323: len = sizeof(struct sockaddr_in);
#####: 1324: rc = getsockname( singinit_listen_sock, (struct sockaddr *) &sin, &len );
#####: 1325: MPIU_Snprintf(port_c, sizeof(port_c), "%d",ntohs(sin.sin_port));
#####: 1326: rc = listen(singinit_listen_sock, 5);
-: 1327:
#####: 1328: PMIU_printf( PMI_debug_init, "Starting mpiexec with %s\n", port_c );
-: 1329:
-: 1330: /* Launch the mpiexec process with the name of this port */
#####: 1331: pid = fork();
#####: 1332: if (pid < 0) {
#####: 1333: perror("PMII_singinit: fork failed");
#####: 1334: exit(-1);
-: 1335: }
#####: 1336: else if (pid == 0) {
#####: 1337: newargv[0] = "mpiexec";
#####: 1338: newargv[1] = "-pmi_args";
#####: 1339: newargv[2] = port_c;
-: 1340: /* FIXME: Use a valid hostname */
#####: 1341: newargv[3] = "default_interface"; /* default interface name, for now */
#####: 1342: newargv[4] = "default_key"; /* default authentication key, for now */
#####: 1343: MPIU_Snprintf(charpid, sizeof(charpid), "%d",getpid());
#####: 1344: newargv[5] = charpid;
#####: 1345: newargv[6] = NULL;
#####: 1346: rc = execvp(newargv[0], (char **)newargv);
#####: 1347: perror("PMII_singinit: execv failed");
#####: 1348: PMIU_printf(1, " This singleton init program attempted to access some feature\n");
#####: 1349: PMIU_printf(1, " for which process manager support was required, e.g. spawn or universe_size.\n");
#####: 1350: PMIU_printf(1, " But the necessary mpiexec is not in your path.\n");
#####: 1351: return(-1);
-: 1352: }
-: 1353: else
-: 1354: {
-: 1355: char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE];
-: 1356: char *p;
#####: 1357: int connectStdio = 0;
-: 1358:
-: 1359: /* Allow one connection back from the created mpiexec program */
#####: 1360: PMI_fd = accept_one_connection(singinit_listen_sock);
#####: 1361: if (PMI_fd < 0) {
#####: 1362: PMIU_printf( 1, "Failed to establish singleton init connection\n" );
#####: 1363: return PMI_FAIL;
-: 1364: }
-: 1365: /* Execute the singleton init protocol */
#####: 1366: rc = PMIU_readline( PMI_fd, buf, PMIU_MAXLINE );
#####: 1367: PMIU_printf( PMI_debug_init, "Singinit: read %s\n", buf );
-: 1368:
#####: 1369: PMIU_parse_keyvals( buf );
#####: 1370: PMIU_getval( "cmd", cmd, PMIU_MAXLINE );
#####: 1371: if (strcmp( cmd, "singinit" ) != 0) {
#####: 1372: PMIU_printf( 1, "unexpected command from PM: %s\n", cmd );
#####: 1373: return PMI_FAIL;
-: 1374: }
#####: 1375: p = PMIU_getval( "authtype", cmd, PMIU_MAXLINE );
#####: 1376: if (p && strcmp( cmd, "none" ) != 0) {
#####: 1377: PMIU_printf( 1, "unsupported authentication method %s\n", cmd );
#####: 1378: return PMI_FAIL;
-: 1379: }
-: 1380: /* p = PMIU_getval( "authstring", cmd, PMIU_MAXLINE ); */
-: 1381:
-: 1382: /* If we're successful, send back our own singinit */
#####: 1383: rc = MPIU_Snprintf( buf, PMIU_MAXLINE,
-: 1384: "cmd=singinit pmi_version=%d pmi_subversion=%d stdio=yes authtype=none\n",
-: 1385: PMI_VERSION, PMI_SUBVERSION );
#####: 1386: if (rc < 0) {
#####: 1387: return PMI_FAIL;
-: 1388: }
#####: 1389: PMIU_printf( PMI_debug_init, "GetResponse with %s\n", buf );
-: 1390:
#####: 1391: rc = GetResponse( buf, "singinit_info", 0 );
#####: 1392: if (rc != 0) {
#####: 1393: PMIU_printf( 1, "GetResponse failed\n" );
#####: 1394: return PMI_FAIL;
-: 1395: }
#####: 1396: p = PMIU_getval( "versionok", cmd, PMIU_MAXLINE );
#####: 1397: if (p && strcmp( cmd, "yes" ) != 0) {
#####: 1398: PMIU_printf( 1, "Process manager needs a different PMI version\n" );
#####: 1399: return PMI_FAIL;
-: 1400: }
#####: 1401: p = PMIU_getval( "stdio", cmd, PMIU_MAXLINE );
#####: 1402: if (p && strcmp( cmd, "yes" ) == 0) {
#####: 1403: PMIU_printf( PMI_debug_init, "PM agreed to connect stdio\n" );
#####: 1404: connectStdio = 1;
-: 1405: }
#####: 1406: p = PMIU_getval( "kvsname", singinit_kvsname, sizeof(singinit_kvsname) );
#####: 1407: PMIU_printf( PMI_debug_init, "kvsname to use is %s\n",
-: 1408: singinit_kvsname );
-: 1409:
#####: 1410: if (connectStdio) {
#####: 1411: PMIU_printf( PMI_debug_init,
-: 1412: "Accepting three connections for stdin, out, err\n" );
#####: 1413: stdin_sock = accept_one_connection(singinit_listen_sock);
#####: 1414: dup2(stdin_sock, 0);
#####: 1415: stdout_sock = accept_one_connection(singinit_listen_sock);
#####: 1416: dup2(stdout_sock,1);
#####: 1417: stderr_sock = accept_one_connection(singinit_listen_sock);
#####: 1418: dup2(stderr_sock,2);
-: 1419: }
#####: 1420: PMIU_printf( PMI_debug_init, "Done with singinit handshake\n" );
-: 1421: }
#####: 1422: return 0;
-: 1423:}
-: 1424:
-: 1425:/* Promote PMI to a fully initialized version if it was started as
-: 1426: a singleton init */
-: 1427:static int PMIi_InitIfSingleton(void)
|
13776: 1428:{
-: 1429: int rc;
-: 1430: static int firstcall = 1;
-: 1431:
13776: 1432: if (PMI_initialized != SINGLETON_INIT_BUT_NO_PM || !firstcall) return 0;
-: 1433:
-: 1434: /* We only try to init as a singleton the first time */
|
#####: 1435: firstcall = 0;
-: 1436:
-: 1437: /* First, start (if necessary) an mpiexec, connect to it,
-: 1438: and start the singleton init handshake */
#####: 1439: rc = PMII_singinit();
-: 1440:
#####: 1441: if (rc < 0)
#####: 1442: return(-1);
#####: 1443: PMI_initialized = SINGLETON_INIT_WITH_PM; /* do this right away */
#####: 1444: PMI_size = 1;
#####: 1445: PMI_rank = 0;
#####: 1446: PMI_debug = 0;
#####: 1447: PMI_spawned = 0;
-: 1448:
#####: 1449: PMII_getmaxes( &PMI_kvsname_max, &PMI_keylen_max, &PMI_vallen_max );
-: 1450:
-: 1451: /* FIXME: We need to support a distinct kvsname for each
-: 1452: process group */
#####: 1453: PMI_KVS_Put( singinit_kvsname, cached_singinit_key, cached_singinit_val );
-: 1454:
#####: 1455: return 0;
-: 1456:}
-: 1457:
-: 1458:static int accept_one_connection(int list_sock)
#####: 1459:{
-: 1460: int gotit, new_sock;
-: 1461: struct sockaddr_in from;
-: 1462: socklen_t len;
-: 1463:
#####: 1464: len = sizeof(from);
#####: 1465: gotit = 0;
#####: 1466: while ( ! gotit )
-: 1467: {
#####: 1468: new_sock = accept(list_sock, (struct sockaddr *)&from, &len);
#####: 1469: if (new_sock == -1)
-: 1470: {
#####: 1471: if (errno == EINTR) /* interrupted? If so, try again */
#####: 1472: continue;
-: 1473: else
-: 1474: {
#####: 1475: PMIU_printf(1, "accept failed in accept_one_connection\n");
#####: 1476: exit(-1);
-: 1477: }
-: 1478: }
-: 1479: else
#####: 1480: gotit = 1;
-: 1481: }
#####: 1482: return(new_sock);
-: 1483:}
-: 1484:
-: 1485:#endif
-: 1486:/* end USE_PMI_PORT */
-: 1487:
-: 1488:/* Get the FD to use for PMI operations. If a port is used, rather than
-: 1489: a pre-established FD (i.e., via pipe), this routine will handle the
-: 1490: initial handshake.
-: 1491:*/
-: 1492:static int getPMIFD( int *notset )
|
4381: 1493:{
-: 1494: char *p;
-: 1495:
-: 1496: /* Set the default */
4381: 1497: PMI_fd = -1;
-: 1498:
4381: 1499: p = getenv( "PMI_FD" );
-: 1500:
4381: 1501: if (p) {
|
#####: 1502: PMI_fd = atoi( p );
#####: 1503: return 0;
-: 1504: }
-: 1505:
-: 1506:#ifdef USE_PMI_PORT
|
4381: 1507: p = getenv( "PMI_PORT" );
4381: 1508: if (p) {
-: 1509: int portnum;
-: 1510: char hostname[MAXHOSTNAME+1];
-: 1511: char *pn, *ph;
4381: 1512: int id = 0;
-: 1513:
-: 1514: /* Connect to the indicated port (in format hostname:portnumber)
-: 1515: and get the fd for the socket */
-: 1516:
-: 1517: /* Split p into host and port */
4381: 1518: pn = p;
4381: 1519: ph = hostname;
61334: 1520: while (*pn && *pn != ':' && (ph - hostname) < MAXHOSTNAME) {
52572: 1521: *ph++ = *pn++;
-: 1522: }
4381: 1523: *ph = 0;
-: 1524:
4381: 1525: if (PMI_debug) {
-: 1526: DBG_PRINTF( ("Connecting to %s\n", p) );
-: 1527: }
4381: 1528: if (*pn == ':') {
4381: 1529: portnum = atoi( pn+1 );
-: 1530: /* FIXME: Check for valid integer after : */
-: 1531: /* This routine only gets the fd to use to talk to
-: 1532: the process manager. The handshake below is used
-: 1533: to setup the initial values */
4381: 1534: PMI_fd = PMII_Connect_to_pm( hostname, portnum );
4381: 1535: if (PMI_fd < 0) {
|
#####: 1536: PMIU_printf( 1, "Unable to connect to %s on %d\n",
-: 1537: hostname, portnum );
#####: 1538: return -1;
-: 1539: }
-: 1540: }
-: 1541: else {
#####: 1542: PMIU_printf( 1, "unable to decode hostport from %s\n", p );
#####: 1543: return PMI_FAIL;
-: 1544: }
-: 1545:
-: 1546: /* We should first handshake to get size, rank, debug. */
|
4381: 1547: p = getenv( "PMI_ID" );
4381: 1548: if (p) {
-: 1549: id = atoi( p );
-: 1550: /* PMII_Set_from_port sets up the values that are delivered
-: 1551: by enviroment variables when a separate port is not used */
|
#####: 1552: PMII_Set_from_port( PMI_fd, id );
#####: 1553: *notset = 0;
-: 1554: }
|
4381: 1555: return 0;
-: 1556: }
-: 1557:#endif
-: 1558:
-: 1559: /* Singleton init case - its ok to return success with no fd set */
|
#####: 1560: return 0;
-: 1561:}
|