Beispiel #1
0
/* 
 * This is the client side of the PMIserver setup.  It communicates to the
 * client the information needed to connect to the server (currently the
 * FD of a pre-existing socket).
 *
 * The env_pmi_fd and port must be static because putenv doesn't make a copy
 * of them.  It is ok to use static variable since this is called only within
 * the client; this routine will be called only once (in the forked process, 
 * before the exec).
 *
 * Another wrinkle is that in order to support -(g)envnone (no environment
 * variables in context of created process), we need to add the environment
 * variables to the ones set *after* environment variables are removed, rather
 * than using putenv.
 */
int PMISetupInClient( int usePort, PMISetup *pmiinfo )
{
    static char env_pmi_fd[100];
    static char env_pmi_port[1024];

    if (usePort == 0) {
	close( pmiinfo->fdpair[0] );
	MPIU_Snprintf( env_pmi_fd, sizeof(env_pmi_fd), "PMI_FD=%d" , 
		       pmiinfo->fdpair[1] );
	if (MPIE_Putenv( pmiinfo->pWorld, env_pmi_fd )) {
	    MPIU_Internal_error_printf( "Could not set environment PMI_FD" );
	    return 1;
	}
    }
    else {
	/* We must communicate the port name to the process */
	if (pmiinfo->portName) {
	    MPIU_Snprintf( env_pmi_port, sizeof(env_pmi_port), "PMI_PORT=%s",
			   pmiinfo->portName );
	    if (MPIE_Putenv( pmiinfo->pWorld, env_pmi_port )) {
		MPIU_Internal_error_printf( "Could not set environment PMI_PORT" );
		perror( "Reason: " );
		return 1;
	    }
	}
	else {
	    MPIU_Internal_error_printf( "Required portname was not defined\n" );
	    return 1;
	}
	
    }
    /* Indicate that this is a spawned process */
    /* MPIE_Putenv( pmiinfo->pWorld, "PMI_SPAWNED=1" ); */
    return 0;
}
Beispiel #2
0
int MPIR_Assert_fail_fmt(const char *cond, const char *file_name, int line_num, const char *fmt, ...)
{
    char msg[MPIU_ASSERT_FMT_MSG_MAX_SIZE] = {'\0'};
    va_list vl;

    va_start(vl,fmt);
    vsnprintf(msg, sizeof(msg), fmt, vl); /* don't check rc, can't handle it anyway */

    MPL_VG_PRINTF_BACKTRACE("Assertion failed in file %s at line %d: %s\n",
                            file_name, line_num, cond);
    MPL_VG_PRINTF_BACKTRACE("%s\n", msg);

    MPIU_Internal_error_printf("Assertion failed in file %s at line %d: %s\n",
                               file_name, line_num, cond);
    MPIU_Internal_error_printf("%s\n", msg);

    MPIU_DBG_MSG_FMT(ALL, TERSE,
                     (MPIU_DBG_FDEST,
                      "Assertion failed in file %s at line %d: %s",
                      file_name, line_num, cond));
    MPIU_DBG_MSG_FMT(ALL, TERSE, (MPIU_DBG_FDEST,"%s",msg));

    MPID_Abort(NULL, MPI_SUCCESS, 1, NULL);
    return MPI_ERR_INTERN; /* never get here, abort should kill us */
}
Beispiel #3
0
int MPIR_Assert_fail(const char *cond, const char *file_name, int line_num)
{
    MPL_VG_PRINTF_BACKTRACE("Assertion failed in file %s at line %d: %s\n",
                            file_name, line_num, cond);
    MPIU_Internal_error_printf("Assertion failed in file %s at line %d: %s\n",
                               file_name, line_num, cond);
    MPIU_DBG_MSG_FMT(ALL, TERSE,
                     (MPIU_DBG_FDEST,
                      "Assertion failed in file %s at line %d: %s",
                      file_name, line_num, cond));
    MPID_Abort(NULL, MPI_SUCCESS, 1, NULL);
    return MPI_ERR_INTERN; /* never get here, abort should kill us */
}
Beispiel #4
0
/* Handle an incoming get_my_kvsname command */
static int fPMI_Handle_get_my_kvsname( PMIProcess *pentry )
{
    char outbuf[PMIU_MAXLINE];
    PMIKVSpace *kvs;

    kvs = pentry->group->kvs;
    if (kvs && kvs->kvsname) {
	MPIU_Snprintf( outbuf, PMIU_MAXLINE, "cmd=my_kvsname kvsname=%s\n",
		       kvs->kvsname );
    }
    else {
	MPIU_Internal_error_printf( "Group has no associated KVS" );
	return -1;
    }
    PMIWriteLine( pentry->fd, outbuf );
    DBG_PRINTFCOND(pmidebug,( "%s", outbuf ));
    return 0;
}
Beispiel #5
0
void MPIR_Add_finalize( int (*f)( void * ), void *extra_data, int priority )
{
    /* --BEGIN ERROR HANDLING-- */
    if (fstack_sp >= MAX_FINALIZE_FUNC) {
	/* This is a little tricky.  We may want to check the state of
	   MPIR_Process.initialized to decide how to signal the error */
	(void)MPIU_Internal_error_printf( "overflow in finalize stack!\n" );
	if (MPIR_Process.initialized == MPICH_WITHIN_MPI) {
	    MPID_Abort( NULL, MPI_SUCCESS, 13, NULL );
	}
	else {
	    exit(1);
	}
    }
    /* --END ERROR HANDLING-- */
    fstack[fstack_sp].f            = f;
    fstack[fstack_sp].priority     = priority;
    fstack[fstack_sp++].extra_data = extra_data;

    if (priority > fstack_max_priority) 
	fstack_max_priority = priority;
}
Beispiel #6
0
/* Create a kvs and return a pointer to it */
static PMIKVSpace *fPMIKVSAllocate( void )
{
    PMIKVSpace *kvs, **kPrev, *k;
    int        rc;
    static int kvsnum = 0;    /* Used to generate names */

    /* Create the space */
    kvs = (PMIKVSpace *)MPIU_Malloc( sizeof(PMIKVSpace) );
    if (!kvs) {
	MPIU_Internal_error_printf( "too many kvs's\n" );
	return 0;
    }
    /* We include the pid of the PMI server as a way to allow multiple
       PMI servers to coexist.  This is needed to support connect/accept
       operations when multiple mpiexec's are used, and the KVS space
       is served directly by mpiexec (it should really have the 
       hostname as well, just to avoid getting the same pid on two
       different hosts, but this is probably good enough for most
       uses) */
    MPIU_Snprintf( (char *)(kvs->kvsname), MAXNAMELEN, "kvs_%d_%d", 
		   (int)getpid(), kvsnum++ );
    kvs->pairs     = 0;
    kvs->lastByIdx = 0;
    kvs->lastIdx   = -1;

    /* Insert into the list of KV spaces */
    kPrev = &pmimaster.kvSpaces;
    k     = pmimaster.kvSpaces;
    while (k) {
	rc = strcmp( k->kvsname, kvs->kvsname );
	if (rc > 0) break;
	kPrev = &k->nextKVS;
	k     = k->nextKVS;
    }
    kvs->nextKVS = k;
    *kPrev = kvs;

    return kvs;
}
Beispiel #7
0
static int PMIKVSFree( PMIKVSpace *kvs )
{
    PMIKVPair *p, *pNext;
    PMIKVSpace **kPrev, *k;
    int        rc;
    
    /* Recover the pairs */
    p = kvs->pairs;
    while (p) {
	pNext = p->nextPair;
	MPIU_Free( p );
	p = pNext;
    }

    /* Recover the KVS space, and remove it from the master's list */
    kPrev = &pmimaster.kvSpaces;
    k     = pmimaster.kvSpaces;
    rc    = 1;
    while (k) {
	rc = strcmp( k->kvsname, kvs->kvsname );
	if (rc == 0) {
	    *kPrev = k->nextKVS;
	    MPIU_Free( k );
	    break;
	}
	kPrev = &(k->nextKVS);
	k = k->nextKVS;
    }
    
    /* Note that if we did not find the kvs, we have an internal 
       error, since all kv spaces are maintained within the pmimaster list */
    if (rc != 0) {
	MPIU_Internal_error_printf( "Could not find KV Space %s\n", 
				    kvs->kvsname );
	return 1;
    }
    return 0;
}
Beispiel #8
0
/* *slen is the length of the string, including the null terminator.  So if the
   resulting string is |foo\0bar\0|, then *slen == 8. */
static int connToStringKVS( char **buf_p, int *slen, MPIDI_PG_t *pg )
{
    char *string = 0;
    char *pg_idStr = (char *)pg->id;      /* In the PMI/KVS space,
					     the pg id is a string */
    char buf[MPIDI_MAX_KVS_VALUE_LEN];
    int   i, j, vallen, rc, mpi_errno = MPI_SUCCESS, len;
    int   curSlen;

    /* Make an initial allocation of a string with an estimate of the
       needed space */
    len = 0;
    curSlen = 10 + pg->size * 128;
    string = (char *)MPIU_Malloc( curSlen );

    /* Start with the id of the pg */
    while (*pg_idStr && len < curSlen) 
	string[len++] = *pg_idStr++;
    string[len++] = 0;
    
    /* Add the size of the pg */
    MPIU_Snprintf( &string[len], curSlen - len, "%d", pg->size );
    while (string[len]) len++;
    len++;

    for (i=0; i<pg->size; i++) {
	rc = getConnInfoKVS( i, buf, MPIDI_MAX_KVS_VALUE_LEN, pg );
	if (rc) {
	    MPIU_Internal_error_printf( 
		    "Panic: getConnInfoKVS failed for %s (rc=%d)\n", 
		    (char *)pg->id, rc );
	}
#ifndef USE_PERSISTENT_SHARED_MEMORY
	/* FIXME: This is a hack to avoid including shared-memory 
	   queue names in the business card that may be used
	   by processes that were not part of the same COMM_WORLD. 
	   To fix this, the shared memory channels should look at the
	   returned connection info and decide whether to use 
	   sockets or shared memory by determining whether the
	   process is in the same MPI_COMM_WORLD. */
	/* FIXME: The more general problem is that the connection information
	   needs to include some information on the range of validity (e.g.,
	   all processes, same comm world, particular ranks), and that
	   representation needs to be scalable */
/*	printf( "Adding key %s value %s\n", key, val ); */
	{
	char *p = strstr( buf, "$shm_host" );
	if (p) p[1] = 0;
	/*	    printf( "(fixed) Adding key %s value %s\n", key, val ); */
	}
#endif
	/* Add the information to the output buffer */
	vallen = strlen(buf);
	/* Check that this will fix in the remaining space */
	if (len + vallen + 1 >= curSlen) {
	    char *nstring = 0;
            curSlen += (pg->size - i) * (vallen + 1 );
	    nstring = MPIU_Realloc( string, curSlen);
	    if (!nstring) {
		MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER,"**nomem");
	    }
	    string = nstring;
	}
	/* Append to string */
	for (j=0; j<vallen+1; j++) {
	    string[len++] = buf[j];
	}
    }

    MPIU_Assert(len <= curSlen);

    *buf_p = string;
    *slen  = len;
 fn_exit:
    return mpi_errno;
 fn_fail:
    if (string) MPIU_Free(string);
    goto fn_exit;
}