|
Packit |
0848f5 |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
*
|
|
Packit |
0848f5 |
* (C) 2006 by Argonne National Laboratory.
|
|
Packit |
0848f5 |
* See COPYRIGHT in top-level directory.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Test of MPI_Comm_join. This should work even when each process
|
|
Packit |
0848f5 |
* is started as a singleton process.
|
|
Packit |
0848f5 |
*
|
|
Packit |
0848f5 |
* To run
|
|
Packit |
0848f5 |
*
|
|
Packit |
0848f5 |
* Start the server:
|
|
Packit |
0848f5 |
*
|
|
Packit |
0848f5 |
* ./singjoin -s -p 54321
|
|
Packit |
0848f5 |
*
|
|
Packit |
0848f5 |
* In a separate shell, start the client:
|
|
Packit |
0848f5 |
*
|
|
Packit |
0848f5 |
* ./singjoin -c -p 54321
|
|
Packit |
0848f5 |
*
|
|
Packit |
0848f5 |
* where "54321" is some available port number.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Include mpitestconf to determine if we can use h_addr or need h_addr_list */
|
|
Packit |
0848f5 |
#include "mpitestconf.h"
|
|
Packit |
0848f5 |
#include <stdio.h>
|
|
Packit |
0848f5 |
#include <stdlib.h>
|
|
Packit |
0848f5 |
#include <string.h>
|
|
Packit |
0848f5 |
#ifndef HAVE_WINDOWS_H
|
|
Packit |
0848f5 |
#include <strings.h>
|
|
Packit |
0848f5 |
#include <unistd.h>
|
|
Packit |
0848f5 |
#include <sys/types.h>
|
|
Packit |
0848f5 |
#include <sys/socket.h>
|
|
Packit |
0848f5 |
#include <netinet/in.h>
|
|
Packit |
0848f5 |
#include <netdb.h>
|
|
Packit |
0848f5 |
#else
|
|
Packit |
0848f5 |
#include <windows.h>
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
#include <mpi.h>
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#ifndef HAVE_WINDOWS_H
|
|
Packit |
0848f5 |
#define SOCKET_FD_TYPE int
|
|
Packit |
0848f5 |
#define INVALID_SOCKET_FD -1
|
|
Packit |
0848f5 |
#else
|
|
Packit |
0848f5 |
#define SOCKET_FD_TYPE SOCKET
|
|
Packit |
0848f5 |
#define INVALID_SOCKET_FD INVALID_SOCKET
|
|
Packit |
0848f5 |
#define bcopy(s1, s2, n) memmove(s2, s1, n)
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
int parse_args(int argc, char **argv);
|
|
Packit |
0848f5 |
void usage(char *name);
|
|
Packit |
0848f5 |
SOCKET_FD_TYPE server_routine(int portnum);
|
|
Packit |
0848f5 |
SOCKET_FD_TYPE client_routine(int portnum);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
int is_server = 0;
|
|
Packit |
0848f5 |
int is_client = 0;
|
|
Packit |
0848f5 |
int opt_port = 0;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* open a socket, establish a connection with a client, and return the fd */
|
|
Packit |
0848f5 |
SOCKET_FD_TYPE server_routine(int portnum)
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
SOCKET_FD_TYPE listenfd, peer_fd;
|
|
Packit |
0848f5 |
int ret, peer_addr_size;
|
|
Packit |
0848f5 |
struct sockaddr_in server_addr, peer_addr;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
listenfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
Packit |
0848f5 |
if (listenfd == INVALID_SOCKET_FD) {
|
|
Packit |
0848f5 |
perror("server socket");
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
memset(&server_addr, 0, sizeof(server_addr));
|
|
Packit |
0848f5 |
server_addr.sin_family = AF_INET;
|
|
Packit |
0848f5 |
server_addr.sin_addr.s_addr = INADDR_ANY;
|
|
Packit |
0848f5 |
server_addr.sin_port = htons(portnum);
|
|
Packit |
0848f5 |
ret = bind(listenfd, (struct sockaddr *) &server_addr, sizeof(server_addr));
|
|
Packit |
0848f5 |
if (ret < 0) {
|
|
Packit |
0848f5 |
perror("server binding");
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
ret = listen(listenfd, 1024);
|
|
Packit |
0848f5 |
if (ret < 0) {
|
|
Packit |
0848f5 |
perror("server listen");
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
peer_addr_size = sizeof(peer_addr);
|
|
Packit |
0848f5 |
peer_fd = accept(listenfd, (struct sockaddr *) &peer_addr, &peer_addr_size);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (peer_fd < 0) {
|
|
Packit |
0848f5 |
perror("server accept");
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
return peer_fd;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* open a socket, establish a connection with a server, and return the fd */
|
|
Packit |
0848f5 |
SOCKET_FD_TYPE client_routine(int portnum)
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
SOCKET_FD_TYPE sockfd;
|
|
Packit |
0848f5 |
struct sockaddr_in server_addr;
|
|
Packit |
0848f5 |
struct hostent *server_ent;
|
|
Packit |
0848f5 |
char hostname[MPI_MAX_PROCESSOR_NAME];
|
|
Packit |
0848f5 |
int hostnamelen;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
Packit |
0848f5 |
if (sockfd == INVALID_SOCKET_FD) {
|
|
Packit |
0848f5 |
perror("client socket");
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Try to get the processor name from MPI */
|
|
Packit |
0848f5 |
MPI_Get_processor_name(hostname, &hostnamelen);
|
|
Packit |
0848f5 |
server_ent = gethostbyname(hostname);
|
|
Packit |
0848f5 |
if (server_ent == NULL) {
|
|
Packit |
0848f5 |
fprintf(stderr, "gethostbyname fails\n");
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
memset(&server_addr, 0, sizeof(server_addr));
|
|
Packit |
0848f5 |
server_addr.sin_family = AF_INET;
|
|
Packit |
0848f5 |
server_addr.sin_port = htons(portnum);
|
|
Packit |
0848f5 |
/* POSIX might define h_addr_list only and not define h_addr */
|
|
Packit |
0848f5 |
#ifdef HAVE_H_ADDR_LIST
|
|
Packit |
0848f5 |
bcopy(server_ent->h_addr_list[0], (char *) &server_addr.sin_addr.s_addr, server_ent->h_length);
|
|
Packit |
0848f5 |
#else
|
|
Packit |
0848f5 |
bcopy(server_ent->h_addr, (char *) &server_addr.sin_addr.s_addr, server_ent->h_length);
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (connect(sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
|
|
Packit |
0848f5 |
perror("client connect");
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
return sockfd;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
void usage(char *name)
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
fprintf(stderr, "usage: %s [-s|-c] -p <PORT>\n", name);
|
|
Packit |
0848f5 |
fprintf(stderr, " specify one and only one of -s or -c\n");
|
|
Packit |
0848f5 |
fprintf(stderr, " port is mandatory\n");
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#ifdef HAVE_WINDOWS_H
|
|
Packit |
0848f5 |
static int get_option(int argc, char **argv, int arg_cnt)
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
if (argv == NULL) {
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if (*argv == NULL) {
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if (arg_cnt < 0 || arg_cnt >= argc) {
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if (strlen(argv[arg_cnt]) < 2) {
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
return (*(argv[arg_cnt] + 1));
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
int parse_args(int argc, char **argv)
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
#ifndef HAVE_WINDOWS_H
|
|
Packit |
0848f5 |
int c;
|
|
Packit |
0848f5 |
extern char *optarg;
|
|
Packit |
0848f5 |
while ((c = getopt(argc, argv, "csp:")) != -1) {
|
|
Packit |
0848f5 |
switch (c) {
|
|
Packit |
0848f5 |
case 's':
|
|
Packit |
0848f5 |
is_server = 1;
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
case 'c':
|
|
Packit |
0848f5 |
is_client = 1;
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
case 'p':
|
|
Packit |
0848f5 |
opt_port = atoi(optarg);
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
case '?':
|
|
Packit |
0848f5 |
case ':':
|
|
Packit |
0848f5 |
default:
|
|
Packit |
0848f5 |
usage(argv[0]);
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if ((is_client == 0) && (is_server == 0)) {
|
|
Packit |
0848f5 |
usage(argv[0]);
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if (opt_port == 0) {
|
|
Packit |
0848f5 |
usage(argv[0]);
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
return 0;
|
|
Packit |
0848f5 |
#else
|
|
Packit |
0848f5 |
int arg_cnt = 1;
|
|
Packit |
0848f5 |
int c;
|
|
Packit |
0848f5 |
while ((c = get_option(argc, argv, arg_cnt++)) > 0) {
|
|
Packit |
0848f5 |
switch (c) {
|
|
Packit |
0848f5 |
case 's':
|
|
Packit |
0848f5 |
is_server = 1;
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
case 'c':
|
|
Packit |
0848f5 |
is_client = 1;
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
case 'p':
|
|
Packit |
0848f5 |
opt_port = atoi(argv[arg_cnt++]);
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
default:
|
|
Packit |
0848f5 |
usage(argv[0]);
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if ((is_client == 0) && (is_server == 0)) {
|
|
Packit |
0848f5 |
usage(argv[0]);
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if (opt_port == 0) {
|
|
Packit |
0848f5 |
usage(argv[0]);
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
return 0;
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
int main(int argc, char **argv)
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int rank, size;
|
|
Packit |
0848f5 |
SOCKET_FD_TYPE fd = INVALID_SOCKET_FD;
|
|
Packit |
0848f5 |
MPI_Comm intercomm, intracomm;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPI_Init(&argc, &argv);
|
|
Packit |
0848f5 |
MPI_Comm_size(MPI_COMM_WORLD, &size);
|
|
Packit |
0848f5 |
if (size != 1) {
|
|
Packit |
0848f5 |
fprintf(stderr, "This test requires that only one process be in each comm_world\n");
|
|
Packit |
0848f5 |
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if (parse_args(argc, argv) == -1) {
|
|
Packit |
0848f5 |
fprintf(stderr, "Unable to parse the command line arguments\n");
|
|
Packit |
0848f5 |
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (is_server) {
|
|
Packit |
0848f5 |
fd = server_routine(opt_port);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else if (is_client) {
|
|
Packit |
0848f5 |
fd = client_routine(opt_port);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (fd == INVALID_SOCKET_FD) {
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#ifdef SINGLETON_KICK
|
|
Packit |
0848f5 |
/* #warning isn't standard C, so we comment out this directive */
|
|
Packit |
0848f5 |
/* #warning using singleton workaround */
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int *usize, aflag;
|
|
Packit |
0848f5 |
MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_UNIVERSE_SIZE, &usize, &aflag);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPI_Comm_join(fd, &intercomm);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (is_server) {
|
|
Packit |
0848f5 |
MPI_Send(MPI_BOTTOM, 0, MPI_INT, 0, 0, intercomm);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
MPI_Recv(MPI_BOTTOM, 0, MPI_INT, 0, 0, intercomm, MPI_STATUS_IGNORE);
|
|
Packit |
0848f5 |
printf("Completed receive on intercomm\n");
|
|
Packit |
0848f5 |
fflush(stdout);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPI_Intercomm_merge(intercomm, 0, &intracomm);
|
|
Packit |
0848f5 |
MPI_Comm_rank(intracomm, &rank;;
|
|
Packit |
0848f5 |
MPI_Comm_size(intracomm, &size);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
printf("[%d/%d] after Intercomm_merge\n", rank, size);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPI_Comm_free(&intracomm);
|
|
Packit |
0848f5 |
MPI_Comm_disconnect(&intercomm);
|
|
Packit |
0848f5 |
MPI_Finalize();
|
|
Packit |
0848f5 |
return 0;
|
|
Packit |
0848f5 |
}
|