示例#1
0
/* Implement the singleton init handshake.  See the discussion in
   simplepmi.c for the protocol */
int PMI_InitSingletonConnection(int fd, PMIProcess * pmiprocess)
{
    char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE];
    int rc;
    char version[PMIU_MAXLINE], subversion[PMIU_MAXLINE];

    /* We start with the singinit command, wait for the singinit from
     * the client, and then send the singinit_info */
    MPL_snprintf(buf, PMIU_MAXLINE,
                 "cmd=singinit pmi_version=%d pmi_subversion=%d stdio=no authtype=none\n",
                 PMI_VERSION, PMI_SUBVERSION);
    PMIWriteLine(fd, buf);
    PMIReadLine(fd, buf, PMIU_MAXLINE);
    PMIU_parse_keyvals(buf);
    PMIU_getval("cmd", cmd, MAXPMICMD);
    if (strcmp(cmd, "singinit")) {
        PMIU_printf(1, "Unexpected cmd %s\n", cmd);
        return -1;
    }
    /* Could look at authtype */
    /* check version compatibility with PMI client library */
    PMIU_getval("pmi_version", version, PMIU_MAXLINE);
    PMIU_getval("pmi_subversion", subversion, PMIU_MAXLINE);
    if (PMI_VERSION == atoi(version) && PMI_SUBVERSION >= atoi(subversion))
        rc = 0;
    else
        rc = -1;

    MPL_snprintf(buf, PMIU_MAXLINE,
                 "cmd=singinit_info versionok=%s stdio=no kvsname=%s\n",
                 (rc == 0) ? "yes" : "no", (char *) (pmiprocess->group->kvs->kvsname));
    PMIWriteLine(fd, buf);

    return 0;
}
示例#2
0
/*
 * Handle an incoming "put" command
 */
static int fPMI_Handle_put(PMIProcess * pentry)
{
    int rc = 0;
    PMIKVSpace *kvs;
    char kvsname[MAXKVSNAME];
    char message[PMIU_MAXLINE], outbuf[PMIU_MAXLINE];
    char key[MAXKEYLEN], val[MAXVALLEN];

    PMIU_getval("kvsname", kvsname, MAXKVSNAME);
    DBG_PRINTFCOND(pmidebug, ("Put: Finding kvs %s\n", kvsname));

    kvs = fPMIKVSFindSpace(kvsname);
    if (kvs) {
        /* should check here for duplicate key and raise error */
        PMIU_getval("key", key, MAXKEYLEN);
        PMIU_getval("value", val, MAXVALLEN);
        rc = fPMIKVSAddPair(kvs, key, val);
        if (rc == 1) {
            rc = -1;    /* no duplicate keys allowed */
            MPL_snprintf(message, PMIU_MAXLINE, "duplicate_key %s", key);
        } else if (rc == -1) {
            rc = -1;
            MPL_snprintf(message, PMIU_MAXLINE, "no_room_in_kvs_%s", kvsname);
        } else {
            rc = 0;
            MPL_strncpy(message, "success", PMIU_MAXLINE);
        }
    } else {
        rc = -1;
        MPL_snprintf(message, PMIU_MAXLINE, "kvs_%s_not_found", kvsname);
    }
    MPL_snprintf(outbuf, PMIU_MAXLINE, "cmd=put_result rc=%d msg=%s\n", rc, message);
    PMIWriteLine(pentry->fd, outbuf);
    return 0;
}
示例#3
0
/*
 * These routines are called when communication is established through
 * a port instead of an fd, and no information is communicated
 * through environment variables.
 */
static int fPMI_Handle_init_port(PMIProcess * pentry)
{
    char outbuf[PMIU_MAXLINE];

    DBG_PRINTFCOND(pmidebug, ("Entering fPMI_Handle_init_port to start connection\n"));

    /* simple_pmi wants to see cmd=initack after the initack request before
     * the other data */
    PMIWriteLine(pentry->fd, "cmd=initack\n");
    MPL_snprintf(outbuf, PMIU_MAXLINE, "cmd=set size=%d\n", pentry->group->nProcess);
    PMIWriteLine(pentry->fd, outbuf);
    MPL_snprintf(outbuf, PMIU_MAXLINE, "cmd=set rank=%d\n", pentry->pState->wRank);
    PMIWriteLine(pentry->fd, outbuf);
    MPL_snprintf(outbuf, PMIU_MAXLINE, "cmd=set debug=%d\n", pmidebug);
    PMIWriteLine(pentry->fd, outbuf);
    return 0;
}
示例#4
0
/* Handle an incoming get_appnum command */
static int fPMI_Handle_get_appnum(PMIProcess * pentry)
{
    ProcessApp *app = pentry->pState->app;
    char outbuf[PMIU_MAXLINE];
    MPL_snprintf(outbuf, PMIU_MAXLINE, "cmd=appnum appnum=%d\n", app->myAppNum);
    PMIWriteLine(pentry->fd, outbuf);
    DBG_PRINTFCOND(pmidebug, ("%s", outbuf));
    return 0;
}
示例#5
0
/* Handle an incoming get_universe_size command */
static int fPMI_Handle_get_universe_size(PMIProcess * pentry)
{
    char outbuf[PMIU_MAXLINE];
    /* Import the universe size from the process structures */
    MPL_snprintf(outbuf, PMIU_MAXLINE, "cmd=universe_size size=%d\n", pUniv.size);
    PMIWriteLine(pentry->fd, outbuf);
    DBG_PRINTFCOND(pmidebug, ("%s", outbuf));
    return 0;
}
示例#6
0
/* Handle an incoming "get_maxes" command */
static int fPMI_Handle_get_maxes(PMIProcess * pentry)
{
    char outbuf[PMIU_MAXLINE];
    MPL_snprintf(outbuf, PMIU_MAXLINE,
                 "cmd=maxes kvsname_max=%d keylen_max=%d vallen_max=%d\n",
                 MAXKVSNAME, MAXKEYLEN, MAXVALLEN);
    PMIWriteLine(pentry->fd, outbuf);
    DBG_PRINTFCOND(pmidebug, ("%s", outbuf));
    return 0;
}
示例#7
0
/* ------------------------------------------------------------------------- */
static int fPMI_Handle_finalize(PMIProcess * pentry)
{
    char outbuf[PMIU_MAXLINE];

    pentry->pState->status = PROCESS_FINALIZED;

    /* send back an acknowledgement to release the process */
    MPL_snprintf(outbuf, PMIU_MAXLINE, "cmd=finalize_ack\n");
    PMIWriteLine(pentry->fd, outbuf);

    return 0;
}
示例#8
0
/*
 * Handle an incoming "create_kvs" command
 */
static int fPMI_Handle_create_kvs(PMIProcess * pentry)
{
    char kvsname[MAXKVSNAME], outbuf[PMIU_MAXLINE];
    int rc;

    rc = fPMIKVSGetNewSpace(kvsname, sizeof(kvsname));
    if (rc) {
        /* PANIC - allocation failed */
        return 1;
    }
    MPL_snprintf(outbuf, PMIU_MAXLINE, "cmd=newkvs kvsname=%s\n", kvsname);
    PMIWriteLine(pentry->fd, outbuf);
    DBG_PRINTFCOND(pmidebug, ("Handle_create_kvs new name %s\n", kvsname));
    return 0;
}
示例#9
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) {
        MPL_snprintf(outbuf, PMIU_MAXLINE, "cmd=my_kvsname kvsname=%s\n", kvs->kvsname);
    } else {
        MPL_internal_error_printf("Group has no associated KVS");
        return -1;
    }
    PMIWriteLine(pentry->fd, outbuf);
    DBG_PRINTFCOND(pmidebug, ("%s", outbuf));
    return 0;
}
示例#10
0
/*
 * Handle an incoming "barrier" command
 *
 * Need a structure that has the fds for all members of a pmi group
 */
static int fPMI_Handle_barrier(PMIProcess * pentry)
{
    int i;
    PMIGroup *group = pentry->group;

    DBG_PRINTFCOND(pmidebug, ("Entering PMI_Handle_barrier for group %d\n", group->groupID));

    group->nInBarrier++;
    if (group->nInBarrier == group->nProcess) {
        for (i = 0; i < group->nProcess; i++) {
            PMIWriteLine(group->pmiProcess[i]->fd, "cmd=barrier_out\n");
        }
        group->nInBarrier = 0;
    }
    return 0;
}
示例#11
0
/*
 * Handle incoming "getbyidx" command
 */
static int fPMI_Handle_getbyidx( PMIProcess *pentry )
{
    int j, jNext, rc=0;
    PMIKVSpace *kvs;
    char kvsname[MAXKVSNAME], j_char[8], outbuf[PMIU_MAXLINE];
    PMIKVPair *p;

    PMIU_getval( "kvsname", kvsname, MAXKVSNAME );
    kvs = fPMIKVSFindSpace( kvsname );
    if (kvs) {
	PMIU_getval( "idx", j_char, sizeof(j_char) );
	j = atoi( j_char );
	jNext = j+1;
	if (kvs->lastIdx >= 0 && j >= kvs->lastIdx) {
	    for (p = kvs->lastByIdx, j-= kvs->lastIdx; j-- > 0 && p; 
		 p = p->nextPair );
	}
	else {
	    for (p = kvs->pairs; j-- > 0 && p; p = p->nextPair) ;
	}
	if (p) {
	    MPIU_Snprintf( outbuf, PMIU_MAXLINE, "cmd=getbyidx_results "
			   "rc=0 nextidx=%d key=%s val=%s\n",
			   jNext, p->key, p->val );
	    kvs->lastIdx   = jNext-1;
	    kvs->lastByIdx = p;
	}
	else {
	    MPIU_Snprintf( outbuf, PMIU_MAXLINE, "cmd=getbyidx_results rc=-1 "
			   "reason=no_more_keyvals\n" );
	    kvs->lastIdx   = -1;
	    kvs->lastByIdx = 0;
	}
    }
    else {
	rc = -1;
	MPIU_Snprintf( outbuf, PMIU_MAXLINE, "cmd=getbyidx_results rc=-1 "
		  "reason=kvs_%s_not_found\n", kvsname );
    }

    PMIWriteLine( pentry->fd, outbuf );
    DBG_PRINTFCOND(pmidebug,( "%s", outbuf ));
    return rc;
}
示例#12
0
/*
 * Handle an incoming "destroy_kvs" command
 */
static int fPMI_Handle_destroy_kvs(PMIProcess * pentry)
{
    int rc = 0;
    PMIKVSpace *kvs;
    char kvsname[MAXKVSNAME];
    char message[PMIU_MAXLINE], outbuf[PMIU_MAXLINE];

    PMIU_getval("kvsname", kvsname, MAXKVSNAME);
    kvs = fPMIKVSFindSpace(kvsname);
    if (kvs) {
        PMIKVSFree(kvs);
        MPL_snprintf(message, PMIU_MAXLINE, "KVS_%s_successfully_destroyed", kvsname);
    } else {
        MPL_snprintf(message, PMIU_MAXLINE, "KVS %s not found", kvsname);
        rc = -1;
    }
    MPL_snprintf(outbuf, PMIU_MAXLINE, "cmd=kvs_destroyed rc=%d msg=%s\n", rc, message);
    PMIWriteLine(pentry->fd, outbuf);
    return 0;
}
示例#13
0
/*
 * Handle incoming "get" command
 */
static int fPMI_Handle_get( PMIProcess *pentry )
{
    PMIKVSpace *kvs;
    int         rc=0;
    char        kvsname[MAXKVSNAME];
    char        message[PMIU_MAXLINE], key[PMIU_MAXLINE], value[PMIU_MAXLINE];
    char        outbuf[PMIU_MAXLINE];
    
    PMIU_getval( "kvsname", kvsname, MAXKVSNAME );
    DBG_PRINTFCOND(pmidebug,( "Get: Finding kvs %s\n", kvsname ) );

    kvs = fPMIKVSFindSpace( kvsname );
    if (kvs) {
	PMIU_getval( "key", key, PMIU_MAXLINE );
	/* Here we could intercept internal keys, e.g., 
	   pmiPrivate keys. */
	rc = fPMIKVSFindKey( kvs, key, value, sizeof(value) );
	if (rc == 0) {
	    rc = 0;
	    MPIU_Strncpy( message, "success", PMIU_MAXLINE );
	}
	else if (rc) {
	    rc = -1;
	    MPIU_Strncpy( value, "unknown", PMIU_MAXLINE );
	    MPIU_Snprintf( message, PMIU_MAXLINE, "key_%s_not_found", 
			   kvsname );
	}
    }
    else { 
	rc = -1;
	MPIU_Strncpy( value, "unknown", PMIU_MAXLINE );
	MPIU_Snprintf( message, PMIU_MAXLINE, "kvs_%s_not_found", kvsname );
    }
    MPIU_Snprintf( outbuf, PMIU_MAXLINE, 
		   "cmd=get_result rc=%d msg=%s value=%s\n",
		   rc, message, value );
    PMIWriteLine( pentry->fd, outbuf );
    DBG_PRINTFCOND( pmidebug, ("%s", outbuf ));
    return rc;
}
示例#14
0
/* Handle an incoming "init" command */
static int fPMI_Handle_init(PMIProcess * pentry)
{
    char version[PMIU_MAXLINE];
    char subversion[PMIU_MAXLINE];
    char outbuf[PMIU_MAXLINE];
    int rc;

    /* check version compatibility with PMI client library */
    PMIU_getval("pmi_version", version, PMIU_MAXLINE);
    PMIU_getval("pmi_subversion", subversion, PMIU_MAXLINE);
    if (PMI_VERSION == atoi(version) && PMI_SUBVERSION >= atoi(subversion))
        rc = 0;
    else
        rc = -1;

    pentry->pState->status = PROCESS_COMMUNICATING;

    MPL_snprintf(outbuf, PMIU_MAXLINE,
                 "cmd=response_to_init pmi_version=%d pmi_subversion=%d rc=%d\n",
                 PMI_VERSION, PMI_SUBVERSION, rc);
    PMIWriteLine(pentry->fd, outbuf);
    DBG_PRINTFCOND(pmidebug, ("%s", outbuf));
    return 0;
}
示例#15
0
static int fPMI_Handle_spawn(PMIProcess * pentry)
{
    char inbuf[PMIU_MAXLINE];
    char *(args[PMI_MAX_ARGS]);
    char key[MAXKEYLEN];
    char outbuf[PMIU_MAXLINE];
    ProcessWorld *pWorld;
    ProcessApp *app = 0;
    int preputNum = 0, rc;
    int i;
    int totspawns = 0, spawnnum = 0;
    PMIKVSpace *kvs = 0;
    /* Variables for info */
    char curInfoKey[PMI_MAX_INFO_KEY], curInfoVal[PMI_MAX_INFO_VAL];
    int curInfoIdx = -1;

    DBG_PRINTFCOND(pmidebug, ("Entering fPMI_Handle_spawn\n"));

    if (!pentry->spawnWorld) {
        pWorld = (ProcessWorld *) MPL_malloc(sizeof(ProcessWorld), MPL_MEM_PM);
        if (!pWorld)
            return 1;

        pentry->spawnWorld = pWorld;
        pWorld->apps = 0;
        pWorld->nProcess = 0;
        pWorld->nextWorld = 0;
        pWorld->nApps = 0;
        pWorld->worldNum = pUniv.nWorlds++;
        /* FIXME: What should be the defaults for the spawned env?
         * Should the default be the env ov the spawner? */
        pWorld->genv = 0;
        pentry->spawnKVS = fPMIKVSAllocate();
    } else {
        pWorld = pentry->spawnWorld;
    }
    kvs = pentry->spawnKVS;

    /* Note that each mcmd=spawn creates an app.  When all apps
     * are present, then then can be linked to a world.  A
     * spawnmultiple command makes use of multiple mcmd=spawn PMI
     * commands */

    /* Create a new app */
    app = (ProcessApp *) MPL_malloc(sizeof(ProcessApp), MPL_MEM_PM);
    if (!app)
        return 1;
    app->myAppNum = 0;
    app->exename = 0;
    app->arch = 0;
    app->path = 0;
    app->wdir = 0;
    app->hostname = 0;
    app->args = 0;
    app->nArgs = 0;
    app->soft.nelm = 0;
    app->nProcess = 0;
    app->pState = 0;
    app->nextApp = 0;
    app->env = 0;
    app->pWorld = pWorld;

    /* Add to the pentry spawn structure */
    if (pentry->spawnAppTail) {
        pentry->spawnAppTail->nextApp = app;
    } else {
        pentry->spawnApp = app;
        pWorld->apps = app;
    }
    pentry->spawnAppTail = app;

    for (i = 0; i < PMI_MAX_ARGS; i++)
        args[i] = 0;

    /* Get lines until we find either cmd or mcmd (an error) or endcmd
     * (expected end) */
    while ((rc = PMIUBufferedReadLine(pentry, inbuf, sizeof(inbuf))) > 0) {
        char *cmdPtr, *valPtr, *p;

        /* Find the command = format */
        p = inbuf;
        /* Find first nonblank */
        while (*p && isascii(*p) && isspace(*p))
            p++;
        if (!*p) {
            /* Empty string.  Ignore */
            continue;
        }
        cmdPtr = p++;
        /* Find '=' */
        while (*p && *p != '=')
            p++;
        if (!*p) {
            /* No =.  Check for endcmd */
            p--;
            /* Trim spaces */
            while (isascii(*p) && isspace(*p))
                p--;
            /* Add null to end */
            *++p = 0;
            if (strcmp("endcmd", cmdPtr) == 0) {
                break;
            }
            /* FIXME: Otherwise, we have a problem */
            MPL_error_printf("Malformed PMI command (no endcmd seen\n");
            return 1;
        } else {
            *p = 0;
        }

        /* Found an = .  value is the rest of the line */
        valPtr = ++p;
        while (*p && *p != '\n')
            p++;
        if (*p)
            *p = 0;     /* Remove the newline */

        /* Now, process the cmd and value */
        if (strcmp("nprocs", cmdPtr) == 0) {
            app->nProcess = atoi(valPtr);
            pWorld->nProcess += app->nProcess;
        } else if (strcmp("execname", cmdPtr) == 0) {
            app->exename = MPL_strdup(valPtr);
        } else if (strcmp("totspawns", cmdPtr) == 0) {
            /* This tells us how many separate spawn commands
             * we expect to see (e.g., for spawn multiple).
             * Each spawn command is a separate "app" */
            totspawns = atoi(valPtr);
        } else if (strcmp("spawnssofar", cmdPtr) == 0) {
            /* This tells us which app we are (starting from 1) */
            spawnnum = atoi(valPtr);
            app->myAppNum = spawnnum - 1;
        } else if (strcmp("argcnt", cmdPtr) == 0) {
            /* argcnt may not be set before the args */
            app->nArgs = atoi(valPtr);
        } else if (strncmp("arg", cmdPtr, 3) == 0) {
            int argnum;
            /* argcnt may not be set before the args */
            /* Handle arg%d.  Values are 1 - origin */
            argnum = atoi(cmdPtr + 3) - 1;
            if (argnum < 0 || argnum >= PMI_MAX_ARGS) {
                MPL_error_printf
                    ("Malformed PMI Spawn command; the index of an argument in the command is %d but must be between 0 and %d\n",
                     argnum, PMI_MAX_ARGS - 1);
                return 1;
            }
            args[argnum] = MPL_strdup(valPtr);
        } else if (strcmp("preput_num", cmdPtr) == 0) {
            preputNum = atoi(valPtr);
        } else if (strncmp("preput_key_", cmdPtr, 11) == 0) {
            /* Save the key */
            MPL_strncpy(key, valPtr, sizeof(key));
        } else if (strncmp("preput_val_", cmdPtr, 11) == 0) {
            /* Place the key,val into the space associate with the current
             * PMI group */
            fPMIKVSAddPair(kvs, key, valPtr);
        }
        /* Info is on a per-app basis (it is an array of info items in
         * spawn multiple).  We can ignore most info values.
         * The ones that are handled are processed by a
         * separate routine (not yet implemented).
         * simple_pmi.c sends (key,value), so we can keep just the
         * last key and pass the key/value to the registered info
         * handler, along with tha app structure.  Alternately,
         * we could save all info items and let the user's
         * spawner handle it */
        else if (strcmp("info_num", cmdPtr) == 0) {
            /* Number of info values */
            ;
        } else if (strncmp("info_key_", cmdPtr, 9) == 0) {
            /* The actual name has a digit, which indicates *which* info
             * key this is */
            curInfoIdx = atoi(cmdPtr + 9);
            MPL_strncpy(curInfoKey, valPtr, sizeof(curInfoKey));
        } else if (strncmp("info_val_", cmdPtr, 9) == 0) {
            /* The actual name has a digit, which indicates *which* info
             * value this is */
            int idx = atoi(cmdPtr + 9);
            if (idx != curInfoIdx) {
                MPL_error_printf
                    ("Malformed PMI command: info keys and values not ordered as expected (expected value %d but got %d)\n",
                     curInfoIdx, idx);
                return 1;
            } else {
                MPL_strncpy(curInfoVal, valPtr, sizeof(curInfoVal));
                /* Apply this info item */
                fPMIInfoKey(app, curInfoKey, curInfoVal);
                /* printf("Got info %s+%s\n", curInfoKey, curInfoVal); */
            }
        } else {
            MPL_error_printf("Unrecognized PMI subcommand on spawnmult: %s\n", cmdPtr);
            return 1;
        }
    }

    if (app->nArgs > 0) {
        app->args = (const char **) MPL_malloc(app->nArgs * sizeof(char *), MPL_MEM_PM);
        for (i = 0; i < app->nArgs; i++) {
            app->args[i] = args[i];
            args[i] = 0;
        }
    }

    pWorld->nApps++;

    /* Now that we've read the commands, invoke the user's spawn command */
    if (totspawns == spawnnum) {
        PMISetupNewGroup(pWorld->nProcess, kvs);

        if (userSpawner) {
            rc = (*userSpawner) (pWorld, userSpawnerData);
        } else {
            MPL_error_printf("Unable to spawn %s\n", app->exename);
            rc = 1;
            MPIE_PrintProcessWorld(stdout, pWorld);
        }

        MPL_snprintf(outbuf, PMIU_MAXLINE, "cmd=spawn_result rc=%d\n", rc);
        PMIWriteLine(pentry->fd, outbuf);
        DBG_PRINTFCOND(pmidebug, ("%s", outbuf));

        /* Clear for the next spawn */
        pentry->spawnApp = 0;
        pentry->spawnAppTail = 0;
        pentry->spawnKVS = 0;
        pentry->spawnWorld = 0;
    }

    /* If totspawnnum != spawnnum, then we are expecting a
     * spawnmult with additional items */
    return 0;
}