/* Finish setting up the server end of the PMI interface */ int PMISetupFinishInServer( int usePort, PMISetup *pmiinfo, ProcessState *pState ) { if (usePort == 0) { PMIProcess *pmiprocess; /* Close the other end of the socket pair */ close( pmiinfo->fdpair[1] ); /* We must initialize this process in the list of PMI processes. We pass the PMIProcess information to the handler */ pmiprocess = PMISetupNewProcess( pmiinfo->fdpair[0], pState ); MPIE_IORegister( pmiinfo->fdpair[0], IO_READ, PMIServHandleInput, pmiprocess ); } else { /* We defer the step of setting up the process until the client contacts the server. See PMIServAcceptFromPort for the creation of the pmiprocess structure and the initialization of the IO handler for the PMI communication */ /* FIXME: We may need to record some information, such as the curPMIGroup, in the pState or pmiprocess entry */ ; } return 0; }
/* IO Handler for the listen socket Respond to a connection request by creating a new socket, which is then registered. Initialize the startup handshake. */ int PMIServAcceptFromPort( int fd, int rdwr, void *data ) { int newfd; struct sockaddr sock; socklen_t addrlen = sizeof(sock); int id; ProcessUniverse *univ = (ProcessUniverse *)data; ProcessWorld *pWorld = univ->worlds; ProcessApp *app; /* Get the new socket */ MPIE_SYSCALL(newfd,accept,( fd, &sock, &addrlen )); DBG_PRINTF(("Acquired new socket in accept (fd = %d)\n", newfd )); if (newfd < 0) { DBG(perror("Error on accept: " )); return newfd; } #ifdef FOO /* Mark this fd as non-blocking */ flags = fcntl( newfd, F_GETFL, 0 ); if (flags >= 0) { flags |= O_NDELAY; fcntl( newfd, F_SETFL, flags ); } #endif /* Make sure that exec'd processes don't get this fd */ fcntl( newfd, F_SETFD, FD_CLOEXEC ); /* Find the matching process. Do this by reading from the socket and getting the id value with which process was created. */ id = PMI_Init_port_connection( newfd ); if (id >= 0) { /* find the matching entry */ ProcessState *pState = 0; int nSoFar = 0; PMIProcess *pmiprocess; /* This code assigns processes to the states in a pWorld by using the id as the rank, and finding the corresponding process among the ranks */ while (pWorld) { app = pWorld->apps; while (app) { if (app->nProcess > id - nSoFar) { /* Found the matching app */ pState = app->pState + (id - nSoFar); break; } else { nSoFar += app->nProcess; } app = app->nextApp; } pWorld = pWorld->nextWorld; } if (!pState) { /* We have a problem */ MPL_error_printf( "Unable to find process with PMI_ID = %d in the universe", id ); return -1; } /* Now, initialize the connection */ /* Create the new process structure (see PMISetupFinishInServer for this step when a pre-existing FD is used */ DBG_PRINTF( ("Server connection to id = %d on fd %d\n", id, newfd )); pmiprocess = PMISetupNewProcess( newfd, pState ); PMI_Init_remote_proc( newfd, pmiprocess ); MPIE_IORegister( newfd, IO_READ, PMIServHandleInput, pmiprocess ); } else { /* Error, the id should never be less than zero or unset */ /* An alternative would be to dynamically assign the ranks as processes come in (but we'd still need to use the PMI_ID to identify the ProcessApp) */ DBG_PRINTF(("Found an invalid id\n" )); return -1; } /* Return success. */ return 0; }