-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/pmi/simple/simple_pmiutil.c
        -:    0:Graph:simple_pmiutil.gcno
        -:    0:Data:simple_pmiutil.gcda
        -:    0:Runs:4380
        -:    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:/* Allow fprintf to logfile */
        -:    8:/* style: allow:fprintf:1 sig:0 */
        -:    9:
        -:   10:/* Utility functions associated with PMI implementation, but not part of
        -:   11:   the PMI interface itself.  Reading and writing on pipes, signals, and parsing
        -:   12:   key=value messages
        -:   13:*/
        -:   14:#include "pmiconf.h"
        -:   15:
        -:   16:#include <stdio.h>
        -:   17:#ifdef HAVE_STDLIB_H
        -:   18:#include <stdlib.h>
        -:   19:#endif
        -:   20:#include <stdarg.h>
        -:   21:#ifdef HAVE_STRING_H
        -:   22:#include <string.h>
        -:   23:#endif
        -:   24:#ifdef HAVE_UNISTD_H
        -:   25:#include <unistd.h>
        -:   26:#endif
        -:   27:#include <errno.h>
        -:   28:#include "simple_pmiutil.h"
        -:   29:
        -:   30:/* Use the memory definitions from mpich2/src/include */
        -:   31:#include "mpimem.h"
        -:   32:/* Use the MPI error message routines from mpich2/src/include */
        -:   33:#include "mpibase.h"
        -:   34:
        -:   35:#define MAXVALLEN 1024
        -:   36:#define MAXKEYLEN   32
        -:   37:
        -:   38:/* These are not the keyvals in the keyval space that is part of the 
        -:   39:   PMI specification.
        -:   40:   They are just part of this implementation's internal utilities.
        -:   41:*/
        -:   42:struct PMIU_keyval_pairs {
        -:   43:    char key[MAXKEYLEN];
        -:   44:    char value[MAXVALLEN];	
        -:   45:};
        -:   46:static struct PMIU_keyval_pairs PMIU_keyval_tab[64] = { { {0}, {0} } };
        -:   47:static int  PMIU_keyval_tab_idx = 0;
        -:   48:
        -:   49:/* This is used to prepend printed output.  Set the initial value to 
        -:   50:   "unset" */
        -:   51:static char PMIU_print_id[PMIU_IDSIZE] = "unset";
        -:   52:
        -:   53:void PMIU_Set_rank( int PMI_rank )
     4380:   54:{
     4380:   55:    MPIU_Snprintf( PMIU_print_id, PMIU_IDSIZE, "cli_%d", PMI_rank );
     4380:   56:}
        -:   57:void PMIU_SetServer( void )
    #####:   58:{
    #####:   59:    MPIU_Strncpy( PMIU_print_id, "server", PMIU_IDSIZE );
    #####:   60:}
        -:   61:
        -:   62:/* Note that vfprintf is part of C89 */
        -:   63:
        -:   64:/* style: allow:fprintf:1 sig:0 */
        -:   65:/* style: allow:vfprintf:1 sig:0 */
        -:   66:/* This should be combined with the message routines */
        -:   67:void PMIU_printf( int print_flag, const char *fmt, ... )
        6:   68:{
        -:   69:    va_list ap;
        -:   70:    static FILE *logfile= 0;
        -:   71:    
        -:   72:    /* In some cases when we are debugging, the handling of stdout or
        -:   73:       stderr may be unreliable.  In that case, we make it possible to
        -:   74:       select an output file. */
        6:   75:    if (!logfile) {
        -:   76:	char *p;
        6:   77:	p = getenv("PMI_USE_LOGFILE");
        6:   78:	if (p) {
        -:   79:	    char filename[1024];
    #####:   80:	    p = getenv("PMI_ID");
    #####:   81:	    if (p) {
    #####:   82:		MPIU_Snprintf( filename, sizeof(filename), 
        -:   83:			       "testclient-%s.out", p );
    #####:   84:		logfile = fopen( filename, "w" );
        -:   85:	    }
        -:   86:	    else {
    #####:   87:		logfile = fopen( "testserver.out", "w" );
        -:   88:	    }
        -:   89:	}
        -:   90:	else 
        6:   91:	    logfile = stderr;
        -:   92:    }
        -:   93:
        6:   94:    if ( print_flag ) {
        -:   95:	/* MPIU_Error_printf( "[%s]: ", PMIU_print_id ); */
        -:   96:	/* FIXME: Decide what role PMIU_printf should have (if any) and
        -:   97:	   select the appropriate MPIU routine */
        6:   98:	fprintf( logfile, "[%s]: ", PMIU_print_id );
        6:   99:	va_start( ap, fmt );
        6:  100:	vfprintf( logfile, fmt, ap );
        6:  101:	va_end( ap );
        6:  102:	fflush( logfile );
        -:  103:    }
        6:  104:}
        -:  105:
        -:  106:#define MAX_READLINE 1024
        -:  107:/* 
        -:  108: * Return the next newline-terminated string of maximum length maxlen.
        -:  109: * This is a buffered version, and reads from fd as necessary.  A
        -:  110: */
        -:  111:int PMIU_readline( int fd, char *buf, int maxlen )
    49011:  112:{
        -:  113:    static char readbuf[MAX_READLINE];
        -:  114:    static char *nextChar = 0, *lastChar = 0;  /* lastChar is really one past 
        -:  115:						  last char */
        -:  116:    static int  lastErrno = 0;
        -:  117:    static int lastfd = -1;
        -:  118:    int curlen, n;
        -:  119:    char *p, ch;
        -:  120:
        -:  121:    /* Note: On the client side, only one thread at a time should 
        -:  122:       be calling this, and there should only be a single fd.  
        -:  123:       Server side code should not use this routine (see the 
        -:  124:       replacement version in src/pm/util/pmiserv.c) */
    49011:  125:    if (nextChar != lastChar && fd != lastfd) {
    #####:  126:	MPIU_Internal_error_printf( "Panic - buffer inconsistent\n" );
    #####:  127:	return -1;
        -:  128:    }
        -:  129:
    49011:  130:    p      = buf;
    49011:  131:    curlen = 1;    /* Make room for the null */
  2364371:  132:    while (curlen < maxlen) {
  2315360:  133:	if (nextChar == lastChar) {
    49011:  134:	    lastfd = fd;
        -:  135:	    do {
    49011:  136:		n = read( fd, readbuf, sizeof(readbuf)-1 );
    49011:  137:	    } while (n == -1 && errno == EINTR);
    49011:  138:	    if (n == 0) {
        -:  139:		/* EOF */
    #####:  140:		break;
        -:  141:	    }
    49011:  142:	    else if (n < 0) {
        -:  143:		/* Error.  Return a negative value if there is no
        -:  144:		   data.  Save the errno in case we need to return it
        -:  145:		   later. */
    #####:  146:		lastErrno = errno;
    #####:  147:		if (curlen == 1) {
    #####:  148:		    curlen = 0;
        -:  149:		}
        -:  150:		break;
        -:  151:	    }
    49011:  152:	    nextChar = readbuf;
    49011:  153:	    lastChar = readbuf + n;
        -:  154:	    /* Add a null at the end just to make it easier to print
        -:  155:	       the read buffer */
    49011:  156:	    readbuf[n] = 0;
        -:  157:	    /* FIXME: Make this an optional output */
        -:  158:	    /* printf( "Readline %s\n", readbuf ); */
        -:  159:	}
        -:  160:	
  2315360:  161:	ch   = *nextChar++;
  2315360:  162:	*p++ = ch;
  2315360:  163:	curlen++;
  2315360:  164:	if (ch == '\n') break;
        -:  165:    }
        -:  166:
        -:  167:    /* We null terminate the string for convenience in printing */
    49011:  168:    *p = 0;
        -:  169:
        -:  170:    /* Return the number of characters, not counting the null */
    49011:  171:    return curlen-1;
        -:  172:}
        -:  173:
        -:  174:int PMIU_writeline( int fd, char *buf )	
    49668:  175:{
        -:  176:    int size, n;
        -:  177:
    49668:  178:    size = strlen( buf );
    49668:  179:    if ( size > PMIU_MAXLINE ) {
    #####:  180:	buf[PMIU_MAXLINE-1] = '\0';
    #####:  181:	PMIU_printf( 1, "write_line: message string too big: :%s:\n", buf );
        -:  182:    }
    49668:  183:    else if ( buf[strlen( buf ) - 1] != '\n' )  /* error:  no newline at end */
    #####:  184:	    PMIU_printf( 1, "write_line: message string doesn't end in newline: :%s:\n",
        -:  185:		       buf );
        -:  186:    else {
        -:  187:	do {
    49668:  188:	    n = write( fd, buf, size );
    49668:  189:	} while (n == -1 && errno == EINTR);
        -:  190:
    49668:  191:	if ( n < 0 ) {
    #####:  192:	    PMIU_printf( 1, "write_line error; fd=%d buf=:%s:\n", fd, buf );
    #####:  193:	    perror("system msg for write_line failure ");
    #####:  194:	    return(-1);
        -:  195:	}
    49668:  196:	if ( n < size)
    #####:  197:	    PMIU_printf( 1, "write_line failed to write entire message\n" );
        -:  198:    }
    49668:  199:    return 0;
        -:  200:}
        -:  201:
        -:  202:/*
        -:  203: * Given an input string st, parse it into internal storage that can be
        -:  204: * queried by routines such as PMIU_getval.
        -:  205: */
        -:  206:int PMIU_parse_keyvals( char *st )
    49011:  207:{
        -:  208:    char *p, *keystart, *valstart;
        -:  209:    int  offset;
        -:  210:
    49011:  211:    if ( !st )
    #####:  212:	return( -1 );
        -:  213:
    49011:  214:    PMIU_keyval_tab_idx = 0;
    49011:  215:    p = st;
        -:  216:    while ( 1 ) {
   192001:  217:	while ( *p == ' ' )
    71495:  218:	    p++;
        -:  219:	/* got non-blank */
   120506:  220:	if ( *p == '=' ) {
    #####:  221:	    PMIU_printf( 1, "PMIU_parse_keyvals:  unexpected = at character %d in %s\n",
        -:  222:		       p - st, st );
    #####:  223:	    return( -1 );
        -:  224:	}
   120506:  225:	if ( *p == '\n' || *p == '\0' )
    #####:  226:	    return( 0 );	/* normal exit */
        -:  227:	/* got normal character */
   120506:  228:	keystart = p;		/* remember where key started */
   836199:  229:	while ( *p != ' ' && *p != '=' && *p != '\n' && *p != '\0' )
   595187:  230:	    p++;
   120506:  231:	if ( *p == ' ' || *p == '\n' || *p == '\0' ) {
    #####:  232:	    PMIU_printf( 1,
        -:  233:       "PMIU_parse_keyvals: unexpected key delimiter at character %d in %s\n",
        -:  234:		       p - st, st );
    #####:  235:	    return( -1 );
        -:  236:	}
        -:  237:	/* Null terminate the key */
   120506:  238:	*p = 0;
        -:  239:	/* store key */
   120506:  240:        MPIU_Strncpy( PMIU_keyval_tab[PMIU_keyval_tab_idx].key, keystart, 
        -:  241:		      MAXKEYLEN );
        -:  242:
   120506:  243:	valstart = ++p;			/* start of value */
  1720173:  244:	while ( *p != ' ' && *p != '\n' && *p != '\0' )
  1479161:  245:	    p++;
        -:  246:	/* store value */
   120506:  247:        MPIU_Strncpy( PMIU_keyval_tab[PMIU_keyval_tab_idx].value, valstart, 
        -:  248:		      MAXVALLEN );
   120506:  249:	offset = p - valstart;
        -:  250:	/* When compiled with -fPIC, the pgcc compiler generates incorrect
        -:  251:	   code if "p - valstart" is used instead of using the 
        -:  252:	   intermediate offset */
   120506:  253:	PMIU_keyval_tab[PMIU_keyval_tab_idx].value[offset] = '\0';  
   120506:  254:	PMIU_keyval_tab_idx++;
   120506:  255:	if ( *p == ' ' )
    71495:  256:	    continue;
    49011:  257:	if ( *p == '\n' || *p == '\0' )
    49011:  258:	    return( 0 );	/* value has been set to empty */
        -:  259:    }
        -:  260:}
        -:  261:
        -:  262:void PMIU_dump_keyvals( void )
    #####:  263:{
        -:  264:    int i;
    #####:  265:    for (i=0; i < PMIU_keyval_tab_idx; i++) 
    #####:  266:	PMIU_printf(1, "  %s=%s\n",PMIU_keyval_tab[i].key, PMIU_keyval_tab[i].value);
    #####:  267:}
        -:  268:
        -:  269:char *PMIU_getval( const char *keystr, char *valstr, int vallen )
   111637:  270:{
        -:  271:    int i, rc;
        -:  272:    
   209854:  273:    for (i = 0; i < PMIU_keyval_tab_idx; i++) {
   209854:  274:	if ( strcmp( keystr, PMIU_keyval_tab[i].key ) == 0 ) { 
   111637:  275:	    rc = MPIU_Strncpy( valstr, PMIU_keyval_tab[i].value, vallen );
   111637:  276:	    if (rc != 0) {
    #####:  277:		PMIU_printf( 1, "MPIU_Strncpy failed in PMIU_getval\n" );
    #####:  278:		return NULL;
        -:  279:	    }
   111637:  280:	    return valstr;
        -:  281:       } 
        -:  282:    }
    #####:  283:    valstr[0] = '\0';
    #####:  284:    return NULL;
        -:  285:}
        -:  286:
        -:  287:void PMIU_chgval( const char *keystr, char *valstr )
    #####:  288:{
        -:  289:    int i;
        -:  290:    
    #####:  291:    for ( i = 0; i < PMIU_keyval_tab_idx; i++ ) {
    #####:  292:	if ( strcmp( keystr, PMIU_keyval_tab[i].key ) == 0 ) {
    #####:  293:	    MPIU_Strncpy( PMIU_keyval_tab[i].value, valstr, MAXVALLEN - 1 );
    #####:  294:	    PMIU_keyval_tab[i].value[MAXVALLEN - 1] = '\0';
        -:  295:	}
        -:  296:    }
    #####:  297:}