2004-08-25 21:39:08 +04:00
|
|
|
/*
|
2007-04-25 05:55:40 +04:00
|
|
|
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
2005-11-05 22:57:48 +03:00
|
|
|
* University Research and Technology
|
|
|
|
* Corporation. All rights reserved.
|
2006-08-23 07:32:36 +04:00
|
|
|
* Copyright (c) 2004-2006 The University of Tennessee and The University
|
2005-11-05 22:57:48 +03:00
|
|
|
* of Tennessee Research Foundation. All rights
|
|
|
|
* reserved.
|
2004-11-28 23:09:25 +03:00
|
|
|
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
|
|
|
* University of Stuttgart. All rights reserved.
|
2005-03-24 15:43:37 +03:00
|
|
|
* Copyright (c) 2004-2005 The Regents of the University of California.
|
|
|
|
* All rights reserved.
|
Fix a number of OOB issues:
* Remove the connect() timeout code, as it had some nasty race conditions
when connections were established as the trigger was firing. A better
solution has been found for the cluster where this was needed, so just
removing it was easiest.
* When a fatal error (too many connection failures) occurs, set an error
on messages in the queue even if there isn't an active message. The
first message to any peer will be queued without being active (and
so will all subsequent messages until the connection is established),
and the orteds will hang until that first message completes. So if
an orted can never contact it's peer, it will never exit and just sit
waiting for that message to complete.
* Cover an interesting RST condition in the connect code. A connection
can complete the three-way handshake, the connector can even send
some data, but the server side will drop the connection because it
can't move it from the half-connected to fully-connected state because
of space shortage in the listen backlog queue. This causes a RST to
be received first time that recv() is called, which will be when waiting
for the remote side of the OOB ack. In this case, transition the
connection back into a CLOSED state and try to connect again.
* Add levels of debugging, rather than all or nothing, each building on
the previous level. 0 (default) is hard errors. 1 is connection
error debugging info. 2 is all connection info. 3 is more state
info. 4 includes all message info.
* Add some hopefully useful comments
This commit was SVN r14261.
2007-04-08 02:33:30 +04:00
|
|
|
* Copyright (c) 2006-2007 Los Alamos National Security, LLC.
|
|
|
|
* All rights reserved.
|
2004-11-22 04:38:40 +03:00
|
|
|
* $COPYRIGHT$
|
|
|
|
*
|
|
|
|
* Additional copyrights may follow
|
|
|
|
*
|
2004-08-25 21:39:08 +04:00
|
|
|
* $HEADER$
|
2006-03-11 06:09:24 +03:00
|
|
|
*
|
|
|
|
* In windows, many of the socket functions return an EWOULDBLOCK
|
|
|
|
* instead of \ things like EAGAIN, EINPROGRESS, etc. It has been
|
|
|
|
* verified that this will \ not conflict with other error codes that
|
|
|
|
* are returned by these functions \ under UNIX/Linux environments
|
2004-08-25 21:39:08 +04:00
|
|
|
*/
|
2006-03-11 06:09:24 +03:00
|
|
|
|
2006-02-12 04:33:29 +03:00
|
|
|
#include "orte_config.h"
|
2004-10-22 20:06:05 +04:00
|
|
|
#ifdef HAVE_UNISTD_H
|
2004-07-13 02:46:57 +04:00
|
|
|
#include <unistd.h>
|
2004-10-22 20:06:05 +04:00
|
|
|
#endif
|
2004-07-13 02:46:57 +04:00
|
|
|
#include <fcntl.h>
|
2004-10-22 20:06:05 +04:00
|
|
|
#ifdef HAVE_SYS_UIO_H
|
2004-07-15 17:51:40 +04:00
|
|
|
#include <sys/uio.h>
|
2004-10-22 20:06:05 +04:00
|
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
2004-07-13 02:46:57 +04:00
|
|
|
#include <sys/types.h>
|
2004-10-22 20:06:05 +04:00
|
|
|
#endif
|
2006-08-15 00:14:44 +04:00
|
|
|
#include "opal/opal_socket_errno.h"
|
2004-10-22 20:06:05 +04:00
|
|
|
#ifdef HAVE_NETINET_IN_H
|
2004-07-13 02:46:57 +04:00
|
|
|
#include <netinet/in.h>
|
2004-10-22 20:06:05 +04:00
|
|
|
#endif
|
|
|
|
#ifdef HAVE_ARPA_INET_H
|
2004-07-13 02:46:57 +04:00
|
|
|
#include <arpa/inet.h>
|
2004-10-22 20:06:05 +04:00
|
|
|
#endif
|
2005-04-12 02:48:50 +04:00
|
|
|
#ifdef HAVE_NETINET_TCP_H
|
|
|
|
#include <netinet/tcp.h>
|
|
|
|
#endif
|
2005-03-14 23:57:21 +03:00
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
#include "opal/mca/backtrace/backtrace.h"
|
2006-02-12 04:33:29 +03:00
|
|
|
#include "orte/class/orte_proc_table.h"
|
2005-07-04 03:31:27 +04:00
|
|
|
#include "opal/util/output.h"
|
2007-04-25 05:55:40 +04:00
|
|
|
#include "opal/util/if.h"
|
2006-02-12 04:33:29 +03:00
|
|
|
#include "orte/util/univ_info.h"
|
2005-03-14 23:57:21 +03:00
|
|
|
|
2006-02-12 04:33:29 +03:00
|
|
|
#include "orte/mca/gpr/gpr.h"
|
|
|
|
#include "orte/mca/ns/ns.h"
|
|
|
|
#include "orte/mca/errmgr/errmgr.h"
|
2005-03-14 23:57:21 +03:00
|
|
|
|
2004-09-02 03:07:40 +04:00
|
|
|
#include "oob_tcp.h"
|
|
|
|
#include "oob_tcp_peer.h"
|
2004-07-01 18:49:54 +04:00
|
|
|
|
2004-07-13 02:46:57 +04:00
|
|
|
static int mca_oob_tcp_peer_start_connect(mca_oob_tcp_peer_t* peer);
|
2004-07-15 17:51:40 +04:00
|
|
|
static int mca_oob_tcp_peer_event_init(mca_oob_tcp_peer_t* peer);
|
2007-04-25 05:55:40 +04:00
|
|
|
static void mca_oob_tcp_peer_connected(mca_oob_tcp_peer_t* peer, int sd);
|
2004-07-13 02:46:57 +04:00
|
|
|
static void mca_oob_tcp_peer_construct(mca_oob_tcp_peer_t* peer);
|
|
|
|
static void mca_oob_tcp_peer_destruct(mca_oob_tcp_peer_t* peer);
|
2007-04-25 05:55:40 +04:00
|
|
|
static int mca_oob_tcp_peer_send_connect_ack(mca_oob_tcp_peer_t* peer, int sd);
|
|
|
|
static int mca_oob_tcp_peer_recv_connect_ack(mca_oob_tcp_peer_t* peer, int sd);
|
|
|
|
static int mca_oob_tcp_peer_recv_blocking(mca_oob_tcp_peer_t* peer, int sd, void* data, size_t size);
|
|
|
|
static int mca_oob_tcp_peer_send_blocking(mca_oob_tcp_peer_t* peer, int sd, void* data, size_t size);
|
2004-07-13 02:46:57 +04:00
|
|
|
static void mca_oob_tcp_peer_recv_handler(int sd, short flags, void* user);
|
|
|
|
static void mca_oob_tcp_peer_send_handler(int sd, short flags, void* user);
|
2004-08-28 05:15:19 +04:00
|
|
|
static void mca_oob_tcp_peer_timer_handler(int sd, short flags, void* user);
|
2004-07-13 02:46:57 +04:00
|
|
|
static void mca_oob_tcp_peer_dump(mca_oob_tcp_peer_t* peer, const char* msg);
|
|
|
|
|
|
|
|
|
2004-07-01 21:45:34 +04:00
|
|
|
OBJ_CLASS_INSTANCE(
|
|
|
|
mca_oob_tcp_peer_t,
|
2006-07-18 01:51:50 +04:00
|
|
|
opal_free_list_item_t,
|
2004-07-13 02:46:57 +04:00
|
|
|
mca_oob_tcp_peer_construct,
|
|
|
|
mca_oob_tcp_peer_destruct);
|
2004-07-01 21:45:34 +04:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is the constructor function for the mca_oob_tcp_peer
|
|
|
|
* struct. Note that this function and OBJ_NEW should NEVER
|
|
|
|
* be called directly. Instead, use mca_oob_tcp_add_peer
|
|
|
|
*
|
|
|
|
* @param peer a pointer to the mca_oob_tcp_peer_t struct to be initialized
|
|
|
|
* @retval none
|
|
|
|
*/
|
2004-07-13 02:46:57 +04:00
|
|
|
static void mca_oob_tcp_peer_construct(mca_oob_tcp_peer_t* peer)
|
2004-07-01 21:45:34 +04:00
|
|
|
{
|
2005-07-03 20:22:16 +04:00
|
|
|
OBJ_CONSTRUCT(&(peer->peer_send_queue), opal_list_t);
|
2005-07-04 02:45:48 +04:00
|
|
|
OBJ_CONSTRUCT(&(peer->peer_lock), opal_mutex_t);
|
2004-09-30 19:09:29 +04:00
|
|
|
memset(&peer->peer_send_event, 0, sizeof(peer->peer_send_event));
|
|
|
|
memset(&peer->peer_recv_event, 0, sizeof(peer->peer_recv_event));
|
2007-04-25 05:55:40 +04:00
|
|
|
peer->peer_sd = -1;
|
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
memset(&peer->peer6_recv_event, 0, sizeof(peer->peer6_recv_event));
|
|
|
|
memset(&peer->peer6_send_event, 0, sizeof(peer->peer6_send_event));
|
|
|
|
peer->peer6_sd = -1;
|
|
|
|
#endif
|
2004-08-28 05:15:19 +04:00
|
|
|
memset(&peer->peer_timer_event, 0, sizeof(peer->peer_timer_event));
|
2005-07-04 03:09:55 +04:00
|
|
|
opal_evtimer_set(&peer->peer_timer_event, mca_oob_tcp_peer_timer_handler, peer);
|
2004-07-01 21:45:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is the destructor function for the mca_oob_tcp_peer
|
|
|
|
* struct. Note that this function and OBJ_RELEASE should NEVER
|
|
|
|
* be called directly. Instead, use mca_oob_tcp_del_peer
|
|
|
|
*
|
|
|
|
* @param peer a pointer to the mca_oob_tcp_peer_t struct to be destroyed
|
|
|
|
* @retval none
|
|
|
|
*/
|
2004-07-13 02:46:57 +04:00
|
|
|
static void mca_oob_tcp_peer_destruct(mca_oob_tcp_peer_t * peer)
|
2004-07-01 21:45:34 +04:00
|
|
|
{
|
2005-03-14 23:57:21 +03:00
|
|
|
mca_oob_tcp_peer_shutdown(peer);
|
2004-07-13 02:46:57 +04:00
|
|
|
OBJ_DESTRUCT(&(peer->peer_send_queue));
|
2004-07-01 21:45:34 +04:00
|
|
|
OBJ_DESTRUCT(&(peer->peer_lock));
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
2004-07-01 21:45:34 +04:00
|
|
|
|
2004-07-13 02:46:57 +04:00
|
|
|
/*
|
|
|
|
* Initialize events to be used by the peer instance for TCP select/poll callbacks.
|
|
|
|
*/
|
2004-07-15 17:51:40 +04:00
|
|
|
static int mca_oob_tcp_peer_event_init(mca_oob_tcp_peer_t* peer)
|
2004-07-13 02:46:57 +04:00
|
|
|
{
|
2004-09-02 03:07:40 +04:00
|
|
|
memset(&peer->peer_recv_event, 0, sizeof(peer->peer_recv_event));
|
|
|
|
memset(&peer->peer_send_event, 0, sizeof(peer->peer_send_event));
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
memset(&peer->peer6_recv_event, 0, sizeof(peer->peer6_recv_event));
|
|
|
|
memset(&peer->peer6_send_event, 0, sizeof(peer->peer6_send_event));
|
|
|
|
#endif
|
|
|
|
if (peer->peer_sd >= 0) {
|
|
|
|
opal_event_set(
|
|
|
|
&peer->peer_recv_event,
|
|
|
|
peer->peer_sd,
|
|
|
|
OPAL_EV_READ|OPAL_EV_PERSIST,
|
|
|
|
mca_oob_tcp_peer_recv_handler,
|
|
|
|
peer);
|
|
|
|
opal_event_set(
|
|
|
|
&peer->peer_send_event,
|
|
|
|
peer->peer_sd,
|
|
|
|
OPAL_EV_WRITE|OPAL_EV_PERSIST,
|
|
|
|
mca_oob_tcp_peer_send_handler,
|
|
|
|
peer);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
if (peer->peer6_sd >= 0) {
|
|
|
|
opal_event_set(
|
|
|
|
&peer->peer6_recv_event,
|
|
|
|
peer->peer6_sd,
|
|
|
|
OPAL_EV_READ|OPAL_EV_PERSIST,
|
|
|
|
mca_oob_tcp_peer_recv_handler,
|
|
|
|
peer);
|
|
|
|
opal_event_set(
|
|
|
|
&peer->peer6_send_event,
|
|
|
|
peer->peer6_sd,
|
|
|
|
OPAL_EV_WRITE|OPAL_EV_PERSIST,
|
|
|
|
mca_oob_tcp_peer_send_handler,
|
|
|
|
peer);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-02-12 04:33:29 +03:00
|
|
|
return ORTE_SUCCESS;
|
2004-07-01 21:45:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2004-08-03 01:24:00 +04:00
|
|
|
* Initiate the appropriate action based on the state of the connection
|
|
|
|
* to the peer.
|
2004-07-01 21:45:34 +04:00
|
|
|
*
|
|
|
|
*/
|
2004-07-13 02:46:57 +04:00
|
|
|
int mca_oob_tcp_peer_send(mca_oob_tcp_peer_t* peer, mca_oob_tcp_msg_t* msg)
|
|
|
|
{
|
2006-02-12 04:33:29 +03:00
|
|
|
int rc = ORTE_SUCCESS;
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_LOCK(&peer->peer_lock);
|
2004-07-13 02:46:57 +04:00
|
|
|
switch(peer->peer_state) {
|
|
|
|
case MCA_OOB_TCP_CONNECTING:
|
|
|
|
case MCA_OOB_TCP_CONNECT_ACK:
|
|
|
|
case MCA_OOB_TCP_CLOSED:
|
2004-09-02 03:07:40 +04:00
|
|
|
case MCA_OOB_TCP_RESOLVE:
|
2004-07-13 02:46:57 +04:00
|
|
|
/*
|
2004-09-02 03:07:40 +04:00
|
|
|
* queue the message and attempt to resolve the peer address
|
2004-07-13 02:46:57 +04:00
|
|
|
*/
|
2005-07-03 20:22:16 +04:00
|
|
|
opal_list_append(&peer->peer_send_queue, (opal_list_item_t*)msg);
|
2004-08-28 05:15:19 +04:00
|
|
|
if(peer->peer_state == MCA_OOB_TCP_CLOSED) {
|
2004-09-02 03:07:40 +04:00
|
|
|
peer->peer_state = MCA_OOB_TCP_RESOLVE;
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_UNLOCK(&peer->peer_lock);
|
2007-04-25 05:55:40 +04:00
|
|
|
return mca_oob_tcp_resolve(peer);
|
2004-08-28 05:15:19 +04:00
|
|
|
}
|
2004-07-13 02:46:57 +04:00
|
|
|
break;
|
|
|
|
case MCA_OOB_TCP_FAILED:
|
2006-02-12 04:33:29 +03:00
|
|
|
rc = ORTE_ERR_UNREACH;
|
2004-07-13 02:46:57 +04:00
|
|
|
break;
|
|
|
|
case MCA_OOB_TCP_CONNECTED:
|
|
|
|
/*
|
|
|
|
* start the message and queue if not completed
|
|
|
|
*/
|
|
|
|
if (NULL != peer->peer_send_msg) {
|
2005-07-03 20:22:16 +04:00
|
|
|
opal_list_append(&peer->peer_send_queue, (opal_list_item_t*)msg);
|
2004-07-13 02:46:57 +04:00
|
|
|
} else {
|
2004-07-15 17:51:40 +04:00
|
|
|
/*if the send does not complete */
|
|
|
|
if(!mca_oob_tcp_msg_send_handler(msg, peer)) {
|
2004-07-13 02:46:57 +04:00
|
|
|
peer->peer_send_msg = msg;
|
2005-07-04 03:09:55 +04:00
|
|
|
opal_event_add(&peer->peer_send_event, 0);
|
2004-08-03 20:34:59 +04:00
|
|
|
} else {
|
|
|
|
mca_oob_tcp_msg_complete(msg, &peer->peer_name);
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_UNLOCK(&peer->peer_lock);
|
2004-07-13 02:46:57 +04:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lookup a peer by name, create one if it doesn't exist.
|
|
|
|
* @param name Peers globally unique identifier.
|
|
|
|
* @retval Pointer to the newly created struture or NULL on error.
|
|
|
|
*/
|
2005-03-14 23:57:21 +03:00
|
|
|
mca_oob_tcp_peer_t * mca_oob_tcp_peer_lookup(const orte_process_name_t* name)
|
2004-07-01 21:45:34 +04:00
|
|
|
{
|
2004-07-13 02:46:57 +04:00
|
|
|
int rc;
|
Not as bad as this all may look. Tim and I made a significant change to the way we handle the startup of the oob, the seed, etc. We have made it backwards-compatible so that mpirun2 and singleton operations remain working. We had to adjust the name server and gpr as well, plus the process_info structure.
This also includes a checkpoint update to openmpi.c and ompid.c. I have re-enabled the ompid compile.
This latter raises an important point. The trunk compiles the programs like ompid just fine under Linux. It also does just fine for OSX under the dynamic libraries. However, we are seeing errors when compiling under OSX for the static case - the linker seems to have trouble resolving some variable names, even though linker diagnostics show the variables as being defined. Thus, a warning to Mac users that you may have to locally turn things off if you are trying to do static compiles. We ask, however, that you don't commit those changes that turn things off for everyone else - instead, let's try to figure out why the static compile is having a problem, and let everyone else continue to work.
Thanks
Ralph
This commit was SVN r2534.
2004-09-08 07:59:06 +04:00
|
|
|
mca_oob_tcp_peer_t * peer, *old;
|
2005-03-14 23:57:21 +03:00
|
|
|
if (NULL == name) { /* can't look this one up */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_LOCK(&mca_oob_tcp_component.tcp_lock);
|
2005-07-19 16:25:19 +04:00
|
|
|
peer = (mca_oob_tcp_peer_t*)orte_hash_table_get_proc(
|
2005-03-14 23:57:21 +03:00
|
|
|
&mca_oob_tcp_component.tcp_peers, name);
|
2004-09-29 21:18:14 +04:00
|
|
|
if(NULL != peer && memcmp(&peer->peer_name,name,sizeof(peer->peer_name)) == 0) {
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_UNLOCK(&mca_oob_tcp_component.tcp_lock);
|
2004-07-13 02:46:57 +04:00
|
|
|
return peer;
|
|
|
|
}
|
|
|
|
|
2004-08-28 05:15:19 +04:00
|
|
|
/* allocate from free list */
|
2004-07-13 02:46:57 +04:00
|
|
|
MCA_OOB_TCP_PEER_ALLOC(peer, rc);
|
|
|
|
if(NULL == peer) {
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_UNLOCK(&mca_oob_tcp_component.tcp_lock);
|
2004-07-01 21:45:34 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
2004-07-13 02:46:57 +04:00
|
|
|
|
2004-08-03 01:24:00 +04:00
|
|
|
/* initialize peer state */
|
2004-07-13 02:46:57 +04:00
|
|
|
peer->peer_name = *name;
|
2004-09-02 03:07:40 +04:00
|
|
|
peer->peer_addr = NULL;
|
2004-08-03 01:24:00 +04:00
|
|
|
peer->peer_sd = -1;
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
peer->peer6_sd = -1;
|
|
|
|
#endif
|
2004-08-03 01:24:00 +04:00
|
|
|
peer->peer_state = MCA_OOB_TCP_CLOSED;
|
2004-08-04 18:33:02 +04:00
|
|
|
peer->peer_recv_msg = NULL;
|
|
|
|
peer->peer_send_msg = NULL;
|
|
|
|
peer->peer_retries = 0;
|
2004-07-15 17:51:40 +04:00
|
|
|
|
2004-08-28 05:15:19 +04:00
|
|
|
/* add to lookup table */
|
2006-02-12 04:33:29 +03:00
|
|
|
if(ORTE_SUCCESS != orte_hash_table_set_proc(&mca_oob_tcp_component.tcp_peers,
|
2005-03-14 23:57:21 +03:00
|
|
|
&peer->peer_name, peer)) {
|
2004-07-13 02:46:57 +04:00
|
|
|
MCA_OOB_TCP_PEER_RETURN(peer);
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_UNLOCK(&mca_oob_tcp_component.tcp_lock);
|
2004-07-13 02:46:57 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
2004-08-03 01:24:00 +04:00
|
|
|
|
2004-07-14 01:03:03 +04:00
|
|
|
/* if the peer list is over the maximum size, remove one unsed peer */
|
2005-07-03 20:22:16 +04:00
|
|
|
opal_list_prepend(&mca_oob_tcp_component.tcp_peer_list, (opal_list_item_t *) peer);
|
Not as bad as this all may look. Tim and I made a significant change to the way we handle the startup of the oob, the seed, etc. We have made it backwards-compatible so that mpirun2 and singleton operations remain working. We had to adjust the name server and gpr as well, plus the process_info structure.
This also includes a checkpoint update to openmpi.c and ompid.c. I have re-enabled the ompid compile.
This latter raises an important point. The trunk compiles the programs like ompid just fine under Linux. It also does just fine for OSX under the dynamic libraries. However, we are seeing errors when compiling under OSX for the static case - the linker seems to have trouble resolving some variable names, even though linker diagnostics show the variables as being defined. Thus, a warning to Mac users that you may have to locally turn things off if you are trying to do static compiles. We ask, however, that you don't commit those changes that turn things off for everyone else - instead, let's try to figure out why the static compile is having a problem, and let everyone else continue to work.
Thanks
Ralph
This commit was SVN r2534.
2004-09-08 07:59:06 +04:00
|
|
|
if(mca_oob_tcp_component.tcp_peer_limit > 0 &&
|
2005-07-03 20:22:16 +04:00
|
|
|
(int)opal_list_get_size(&mca_oob_tcp_component.tcp_peer_list) >
|
2005-03-14 23:57:21 +03:00
|
|
|
mca_oob_tcp_component.tcp_peer_limit) {
|
2004-07-15 17:51:40 +04:00
|
|
|
old = (mca_oob_tcp_peer_t *)
|
2005-07-03 20:22:16 +04:00
|
|
|
opal_list_get_last(&mca_oob_tcp_component.tcp_peer_list);
|
2004-07-15 17:51:40 +04:00
|
|
|
while(1) {
|
2005-07-03 20:22:16 +04:00
|
|
|
if(0 == opal_list_get_size(&(old->peer_send_queue)) &&
|
2004-07-15 17:51:40 +04:00
|
|
|
NULL == peer->peer_recv_msg) {
|
2005-07-03 20:22:16 +04:00
|
|
|
opal_list_remove_item(&mca_oob_tcp_component.tcp_peer_list,
|
|
|
|
(opal_list_item_t *) old);
|
2004-07-15 17:51:40 +04:00
|
|
|
MCA_OOB_TCP_PEER_RETURN(old);
|
|
|
|
break;
|
|
|
|
} else {
|
2005-07-03 20:22:16 +04:00
|
|
|
old = (mca_oob_tcp_peer_t *) opal_list_get_prev(old);
|
|
|
|
if(opal_list_get_begin(&mca_oob_tcp_component.tcp_peer_list) == (opal_list_item_t*)old) {
|
2004-07-15 17:51:40 +04:00
|
|
|
/* we tried, but we couldn't find one that was valid to get rid
|
|
|
|
* of. Oh well. */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_UNLOCK(&mca_oob_tcp_component.tcp_lock);
|
2004-07-13 02:46:57 +04:00
|
|
|
return peer;
|
2004-07-01 21:45:34 +04:00
|
|
|
}
|
|
|
|
|
2004-09-02 03:07:40 +04:00
|
|
|
|
2006-09-19 23:33:49 +04:00
|
|
|
/*
|
|
|
|
* Try connecting to a peer using all the addresses that peer exported.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int mca_oob_tcp_peer_try_connect(mca_oob_tcp_peer_t* peer)
|
|
|
|
{
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
struct sockaddr_in6 inaddr;
|
|
|
|
#else
|
2006-09-19 23:33:49 +04:00
|
|
|
struct sockaddr_in inaddr;
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
2006-09-19 23:33:49 +04:00
|
|
|
int rc;
|
2007-04-25 05:55:40 +04:00
|
|
|
int connect_sd = -1;
|
|
|
|
opal_socklen_t addrlen;
|
2006-09-19 23:33:49 +04:00
|
|
|
|
|
|
|
do {
|
|
|
|
/* pick an address in round-robin fashion from the list exported by the peer */
|
2007-04-25 05:55:40 +04:00
|
|
|
if(ORTE_SUCCESS != mca_oob_tcp_addr_get_next(peer->peer_addr, (struct sockaddr_storage*) &inaddr)) {
|
2006-09-19 23:33:49 +04:00
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_try_connect: "
|
|
|
|
"mca_oob_tcp_addr_get_next failed with error=%d",
|
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
|
|
|
rc);
|
|
|
|
mca_oob_tcp_peer_close(peer);
|
|
|
|
return ORTE_ERR_UNREACH;
|
|
|
|
}
|
|
|
|
|
Fix a number of OOB issues:
* Remove the connect() timeout code, as it had some nasty race conditions
when connections were established as the trigger was firing. A better
solution has been found for the cluster where this was needed, so just
removing it was easiest.
* When a fatal error (too many connection failures) occurs, set an error
on messages in the queue even if there isn't an active message. The
first message to any peer will be queued without being active (and
so will all subsequent messages until the connection is established),
and the orteds will hang until that first message completes. So if
an orted can never contact it's peer, it will never exit and just sit
waiting for that message to complete.
* Cover an interesting RST condition in the connect code. A connection
can complete the three-way handshake, the connector can even send
some data, but the server side will drop the connection because it
can't move it from the half-connected to fully-connected state because
of space shortage in the listen backlog queue. This causes a RST to
be received first time that recv() is called, which will be when waiting
for the remote side of the OOB ack. In this case, transition the
connection back into a CLOSED state and try to connect again.
* Add levels of debugging, rather than all or nothing, each building on
the previous level. 0 (default) is hard errors. 1 is connection
error debugging info. 2 is all connection info. 3 is more state
info. 4 includes all message info.
* Add some hopefully useful comments
This commit was SVN r14261.
2007-04-08 02:33:30 +04:00
|
|
|
if(mca_oob_tcp_component.tcp_debug >= OOB_TCP_DEBUG_CONNECT) {
|
2006-09-19 23:33:49 +04:00
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_try_connect: "
|
|
|
|
"connecting port %d to: %s:%d\n",
|
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
2007-04-25 05:55:40 +04:00
|
|
|
/* Bug, FIXME: output tcp6_listen_port for AF_INET6 */
|
2006-09-19 23:33:49 +04:00
|
|
|
ntohs(mca_oob_tcp_component.tcp_listen_port),
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
opal_sockaddr2str(&inaddr),
|
|
|
|
ntohs(inaddr.sin6_port)
|
|
|
|
#else
|
2006-09-19 23:33:49 +04:00
|
|
|
inet_ntoa(inaddr.sin_addr),
|
2007-04-25 05:55:40 +04:00
|
|
|
ntohs(inaddr.sin_port)
|
|
|
|
#endif
|
|
|
|
);
|
2006-09-19 23:33:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* start the connect - will likely fail with EINPROGRESS */
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
/* select the right outgoing socket according to the
|
|
|
|
af_family information in inaddr
|
|
|
|
*/
|
|
|
|
if (AF_INET6 == inaddr.sin6_family) {
|
|
|
|
/* if we couldn't initialize an IPv6 device, skip this
|
|
|
|
address */
|
|
|
|
if (peer->peer6_sd < 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
connect_sd = peer->peer6_sd;
|
|
|
|
addrlen = sizeof (struct sockaddr_in6);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (AF_INET == inaddr.sin6_family) {
|
|
|
|
connect_sd = peer->peer_sd;
|
|
|
|
addrlen = sizeof (struct sockaddr_in);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
connect_sd = peer->peer_sd;
|
|
|
|
addrlen = sizeof (struct sockaddr_in);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if(connect(connect_sd, (struct sockaddr*)&inaddr, addrlen) < 0) {
|
2006-09-19 23:33:49 +04:00
|
|
|
/* non-blocking so wait for completion */
|
|
|
|
if(opal_socket_errno == EINPROGRESS || opal_socket_errno == EWOULDBLOCK) {
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
/* I don't know what I'm doing here. Let's hope it results
|
|
|
|
in the right callback. Bug, FIXME
|
|
|
|
*/
|
|
|
|
if (AF_INET == inaddr.sin6_family) {
|
|
|
|
opal_event_add (&peer->peer_send_event, 0);
|
|
|
|
peer->current_af = AF_INET;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (AF_INET6 == inaddr.sin6_family) {
|
|
|
|
opal_event_add (&peer->peer6_send_event, 0);
|
|
|
|
peer->current_af = AF_INET6;
|
|
|
|
}
|
|
|
|
#else
|
2006-09-20 18:29:37 +04:00
|
|
|
opal_event_add(&peer->peer_send_event, 0);
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
2006-09-19 23:33:49 +04:00
|
|
|
|
|
|
|
return ORTE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
Fix a number of OOB issues:
* Remove the connect() timeout code, as it had some nasty race conditions
when connections were established as the trigger was firing. A better
solution has been found for the cluster where this was needed, so just
removing it was easiest.
* When a fatal error (too many connection failures) occurs, set an error
on messages in the queue even if there isn't an active message. The
first message to any peer will be queued without being active (and
so will all subsequent messages until the connection is established),
and the orteds will hang until that first message completes. So if
an orted can never contact it's peer, it will never exit and just sit
waiting for that message to complete.
* Cover an interesting RST condition in the connect code. A connection
can complete the three-way handshake, the connector can even send
some data, but the server side will drop the connection because it
can't move it from the half-connected to fully-connected state because
of space shortage in the listen backlog queue. This causes a RST to
be received first time that recv() is called, which will be when waiting
for the remote side of the OOB ack. In this case, transition the
connection back into a CLOSED state and try to connect again.
* Add levels of debugging, rather than all or nothing, each building on
the previous level. 0 (default) is hard errors. 1 is connection
error debugging info. 2 is all connection info. 3 is more state
info. 4 includes all message info.
* Add some hopefully useful comments
This commit was SVN r14261.
2007-04-08 02:33:30 +04:00
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_try_connect: "
|
|
|
|
"connect to %s:%d failed: %s (%d)",
|
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
opal_sockaddr2str (&inaddr),
|
|
|
|
ntohs(inaddr.sin6_port),
|
|
|
|
#else
|
Fix a number of OOB issues:
* Remove the connect() timeout code, as it had some nasty race conditions
when connections were established as the trigger was firing. A better
solution has been found for the cluster where this was needed, so just
removing it was easiest.
* When a fatal error (too many connection failures) occurs, set an error
on messages in the queue even if there isn't an active message. The
first message to any peer will be queued without being active (and
so will all subsequent messages until the connection is established),
and the orteds will hang until that first message completes. So if
an orted can never contact it's peer, it will never exit and just sit
waiting for that message to complete.
* Cover an interesting RST condition in the connect code. A connection
can complete the three-way handshake, the connector can even send
some data, but the server side will drop the connection because it
can't move it from the half-connected to fully-connected state because
of space shortage in the listen backlog queue. This causes a RST to
be received first time that recv() is called, which will be when waiting
for the remote side of the OOB ack. In this case, transition the
connection back into a CLOSED state and try to connect again.
* Add levels of debugging, rather than all or nothing, each building on
the previous level. 0 (default) is hard errors. 1 is connection
error debugging info. 2 is all connection info. 3 is more state
info. 4 includes all message info.
* Add some hopefully useful comments
This commit was SVN r14261.
2007-04-08 02:33:30 +04:00
|
|
|
inet_ntoa(inaddr.sin_addr),
|
|
|
|
ntohs(inaddr.sin_port),
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
Fix a number of OOB issues:
* Remove the connect() timeout code, as it had some nasty race conditions
when connections were established as the trigger was firing. A better
solution has been found for the cluster where this was needed, so just
removing it was easiest.
* When a fatal error (too many connection failures) occurs, set an error
on messages in the queue even if there isn't an active message. The
first message to any peer will be queued without being active (and
so will all subsequent messages until the connection is established),
and the orteds will hang until that first message completes. So if
an orted can never contact it's peer, it will never exit and just sit
waiting for that message to complete.
* Cover an interesting RST condition in the connect code. A connection
can complete the three-way handshake, the connector can even send
some data, but the server side will drop the connection because it
can't move it from the half-connected to fully-connected state because
of space shortage in the listen backlog queue. This causes a RST to
be received first time that recv() is called, which will be when waiting
for the remote side of the OOB ack. In this case, transition the
connection back into a CLOSED state and try to connect again.
* Add levels of debugging, rather than all or nothing, each building on
the previous level. 0 (default) is hard errors. 1 is connection
error debugging info. 2 is all connection info. 3 is more state
info. 4 includes all message info.
* Add some hopefully useful comments
This commit was SVN r14261.
2007-04-08 02:33:30 +04:00
|
|
|
strerror(opal_socket_errno),
|
|
|
|
opal_socket_errno);
|
2006-09-19 23:33:49 +04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* send our globally unique process identifier to the peer */
|
2007-04-25 05:55:40 +04:00
|
|
|
if((rc = mca_oob_tcp_peer_send_connect_ack(peer, connect_sd)) == ORTE_SUCCESS) {
|
2006-09-19 23:33:49 +04:00
|
|
|
peer->peer_state = MCA_OOB_TCP_CONNECT_ACK;
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
if (AF_INET == inaddr.sin6_family) {
|
|
|
|
opal_event_add (&peer->peer_recv_event, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (AF_INET6 == inaddr.sin6_family) {
|
|
|
|
opal_event_add (&peer->peer6_recv_event, 0);
|
|
|
|
}
|
|
|
|
#else
|
2006-09-19 23:33:49 +04:00
|
|
|
opal_event_add(&peer->peer_recv_event, 0);
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
2006-09-19 23:33:49 +04:00
|
|
|
return ORTE_SUCCESS;
|
|
|
|
} else {
|
|
|
|
opal_output(0,
|
|
|
|
"[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_try_connect: "
|
2006-12-14 21:20:43 +03:00
|
|
|
"mca_oob_tcp_peer_send_connect_ack to %s:%d failed: %s (%d)",
|
2006-09-19 23:33:49 +04:00
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
opal_sockaddr2str (&inaddr),
|
|
|
|
ntohs(inaddr.sin6_port),
|
|
|
|
#else
|
2006-09-19 23:33:49 +04:00
|
|
|
inet_ntoa(inaddr.sin_addr),
|
2007-04-25 05:55:40 +04:00
|
|
|
/* if we didn't successfully connect, wait 1 second and then try again */
|
2006-09-19 23:33:49 +04:00
|
|
|
ntohs(inaddr.sin_port),
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
2007-01-30 23:56:31 +03:00
|
|
|
opal_strerror(rc),
|
2006-09-19 23:33:49 +04:00
|
|
|
rc);
|
|
|
|
}
|
|
|
|
} while(peer->peer_addr->addr_next != 0);
|
|
|
|
|
|
|
|
/* None of the interfaces worked.. */
|
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_try_connect: "
|
|
|
|
"connect to %s:%d failed, connecting over all interfaces failed!",
|
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
opal_sockaddr2str (&inaddr),
|
|
|
|
ntohs(inaddr.sin6_port)
|
|
|
|
#else
|
2006-09-19 23:33:49 +04:00
|
|
|
inet_ntoa(inaddr.sin_addr),
|
2007-04-25 05:55:40 +04:00
|
|
|
ntohs(inaddr.sin_port)
|
|
|
|
#endif
|
|
|
|
);
|
2006-09-19 23:33:49 +04:00
|
|
|
mca_oob_tcp_peer_close(peer);
|
|
|
|
return ORTE_ERR_UNREACH;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-07-01 21:45:34 +04:00
|
|
|
/*
|
2004-07-13 02:46:57 +04:00
|
|
|
* Start a connection to the peer. This will likely not complete,
|
|
|
|
* as the socket is set to non-blocking, so register for event
|
|
|
|
* notification of connect completion. On connection we send
|
|
|
|
* our globally unique process identifier to the peer and wait for
|
|
|
|
* the peers response.
|
|
|
|
*/
|
2006-09-19 23:33:49 +04:00
|
|
|
|
2004-07-13 02:46:57 +04:00
|
|
|
static int mca_oob_tcp_peer_start_connect(mca_oob_tcp_peer_t* peer)
|
|
|
|
{
|
2006-09-19 23:33:49 +04:00
|
|
|
int flags;
|
2004-09-02 03:07:40 +04:00
|
|
|
|
|
|
|
/* create socket */
|
|
|
|
peer->peer_state = MCA_OOB_TCP_CONNECTING;
|
2007-04-25 05:55:40 +04:00
|
|
|
/* adi@2006-10-25: Former Bug. */
|
2004-07-13 02:46:57 +04:00
|
|
|
peer->peer_sd = socket(AF_INET, SOCK_STREAM, 0);
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
peer->peer6_sd = socket(AF_INET6, SOCK_STREAM, 0);
|
|
|
|
if ((peer->peer_sd < 0) && (peer->peer6_sd < 0)) {
|
|
|
|
#else
|
2004-07-13 02:46:57 +04:00
|
|
|
if (peer->peer_sd < 0) {
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
Not as bad as this all may look. Tim and I made a significant change to the way we handle the startup of the oob, the seed, etc. We have made it backwards-compatible so that mpirun2 and singleton operations remain working. We had to adjust the name server and gpr as well, plus the process_info structure.
This also includes a checkpoint update to openmpi.c and ompid.c. I have re-enabled the ompid compile.
This latter raises an important point. The trunk compiles the programs like ompid just fine under Linux. It also does just fine for OSX under the dynamic libraries. However, we are seeing errors when compiling under OSX for the static case - the linker seems to have trouble resolving some variable names, even though linker diagnostics show the variables as being defined. Thus, a warning to Mac users that you may have to locally turn things off if you are trying to do static compiles. We ask, however, that you don't commit those changes that turn things off for everyone else - instead, let's try to figure out why the static compile is having a problem, and let everyone else continue to work.
Thanks
Ralph
This commit was SVN r2534.
2004-09-08 07:59:06 +04:00
|
|
|
struct timeval tv = { 1,0 };
|
2005-07-04 03:31:27 +04:00
|
|
|
opal_output(0,
|
2006-12-14 21:20:43 +03:00
|
|
|
"[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_start_connect: socket() failed: %s (%d)\n",
|
2005-03-14 23:57:21 +03:00
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
2006-12-14 21:20:43 +03:00
|
|
|
strerror(opal_socket_errno),
|
2006-08-15 00:14:44 +04:00
|
|
|
opal_socket_errno);
|
2005-03-19 02:40:08 +03:00
|
|
|
mca_oob_tcp_peer_shutdown(peer);
|
2005-07-04 03:09:55 +04:00
|
|
|
opal_evtimer_add(&peer->peer_timer_event, &tv);
|
2006-02-12 04:33:29 +03:00
|
|
|
return ORTE_ERR_UNREACH;
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
|
|
|
|
2005-10-31 19:21:11 +03:00
|
|
|
/* setup socket options */
|
2007-04-25 05:55:40 +04:00
|
|
|
if (peer->peer_sd >= 0) {
|
|
|
|
mca_oob_tcp_set_socket_options(peer->peer_sd);
|
|
|
|
}
|
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
if (peer->peer6_sd >= 0) {
|
|
|
|
mca_oob_tcp_set_socket_options(peer->peer6_sd);
|
|
|
|
}
|
|
|
|
#endif
|
2005-10-31 19:21:11 +03:00
|
|
|
|
2004-07-13 02:46:57 +04:00
|
|
|
/* setup event callbacks */
|
2004-07-15 17:51:40 +04:00
|
|
|
mca_oob_tcp_peer_event_init(peer);
|
2004-07-13 02:46:57 +04:00
|
|
|
|
|
|
|
/* setup the socket as non-blocking */
|
2007-04-25 05:55:40 +04:00
|
|
|
if (peer->peer_sd >= 0) {
|
|
|
|
if((flags = fcntl(peer->peer_sd, F_GETFL, 0)) < 0) {
|
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_connect: fcntl(F_GETFL) failed: %s (%d)\n",
|
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
|
|
|
strerror(opal_socket_errno),
|
|
|
|
opal_socket_errno);
|
|
|
|
} else {
|
|
|
|
flags |= O_NONBLOCK;
|
|
|
|
if(fcntl(peer->peer_sd, F_SETFL, flags) < 0)
|
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_connect: fcntl(F_SETFL) failed: %s (%d)\n",
|
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
|
|
|
strerror(opal_socket_errno),
|
|
|
|
opal_socket_errno);
|
|
|
|
}
|
2004-09-02 03:07:40 +04:00
|
|
|
}
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
if (peer->peer6_sd >= 0) {
|
|
|
|
if((flags = fcntl(peer->peer6_sd, F_GETFL, 0)) < 0) {
|
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_connect: fcntl(F_GETFL) failed with errno=%d\n",
|
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
|
|
|
opal_socket_errno);
|
|
|
|
} else {
|
|
|
|
flags |= O_NONBLOCK;
|
|
|
|
if(fcntl(peer->peer6_sd, F_SETFL, flags) < 0)
|
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_connect: fcntl(F_SETFL) failed with errno=%d\n",
|
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
|
|
|
opal_socket_errno);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2004-09-02 03:07:40 +04:00
|
|
|
|
2005-08-27 21:03:19 +04:00
|
|
|
/*
|
|
|
|
* We should parse all the IP addresses exported by the peer and try to connect to each of them.
|
|
|
|
*/
|
2006-09-19 23:33:49 +04:00
|
|
|
|
|
|
|
return mca_oob_tcp_peer_try_connect(peer);
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
|
|
|
|
2004-08-03 01:24:00 +04:00
|
|
|
|
2004-07-13 02:46:57 +04:00
|
|
|
/*
|
|
|
|
* Check the status of the connection. If the connection failed, will retry
|
|
|
|
* later. Otherwise, send this processes identifier to the peer on the
|
|
|
|
* newly connected socket.
|
|
|
|
*/
|
2007-04-25 05:55:40 +04:00
|
|
|
static void mca_oob_tcp_peer_complete_connect(mca_oob_tcp_peer_t* peer, int sd)
|
2004-07-13 02:46:57 +04:00
|
|
|
{
|
|
|
|
int so_error = 0;
|
2006-09-15 01:29:51 +04:00
|
|
|
opal_socklen_t so_length = sizeof(so_error);
|
2004-08-03 01:24:00 +04:00
|
|
|
|
2004-07-13 02:46:57 +04:00
|
|
|
/* unregister from receiving event notifications */
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
/* Bug, FIXME: I don't know what I'm doing */
|
|
|
|
if (sd == peer->peer_sd) {
|
|
|
|
opal_event_del (&peer->peer_send_event);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sd == peer->peer6_sd) {
|
|
|
|
opal_event_del (&peer->peer6_send_event);
|
|
|
|
}
|
|
|
|
#else
|
2005-07-04 03:09:55 +04:00
|
|
|
opal_event_del(&peer->peer_send_event);
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
2004-08-03 01:24:00 +04:00
|
|
|
|
2004-07-13 02:46:57 +04:00
|
|
|
/* check connect completion status */
|
2007-04-25 05:55:40 +04:00
|
|
|
if(getsockopt(sd, SOL_SOCKET, SO_ERROR, (char *)&so_error, &so_length) < 0) {
|
2006-12-14 21:20:43 +03:00
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_complete_connect: getsockopt() failed: %s (%d)\n",
|
2005-03-14 23:57:21 +03:00
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
2006-12-14 21:20:43 +03:00
|
|
|
strerror(opal_socket_errno),
|
2006-08-15 00:14:44 +04:00
|
|
|
opal_socket_errno);
|
2004-07-13 02:46:57 +04:00
|
|
|
mca_oob_tcp_peer_close(peer);
|
|
|
|
return;
|
|
|
|
}
|
2006-09-19 23:33:49 +04:00
|
|
|
|
2004-07-13 02:46:57 +04:00
|
|
|
if(so_error == EINPROGRESS) {
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
/* Bug, FIXME: I don't know what I'm doing here */
|
|
|
|
if (sd == peer->peer_sd) {
|
|
|
|
opal_event_add (&peer->peer_send_event, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sd == peer->peer6_sd) {
|
|
|
|
opal_event_add (&peer->peer6_send_event, 0);
|
|
|
|
}
|
|
|
|
#else
|
2005-07-04 03:09:55 +04:00
|
|
|
opal_event_add(&peer->peer_send_event, 0);
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
2004-07-13 02:46:57 +04:00
|
|
|
return;
|
2005-03-19 02:40:08 +03:00
|
|
|
} else if (so_error == ECONNREFUSED || so_error == ETIMEDOUT) {
|
2004-08-28 05:15:19 +04:00
|
|
|
struct timeval tv = { 1,0 };
|
2005-07-04 03:31:27 +04:00
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_complete_connect: "
|
2007-04-25 05:55:40 +04:00
|
|
|
"connection failed: %s (%d) - retrying\n",
|
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
|
|
|
strerror(so_error),
|
|
|
|
so_error);
|
|
|
|
if(mca_oob_tcp_component.tcp_debug >= OOB_TCP_DEBUG_CONNECT) {
|
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_complete_connect: "
|
|
|
|
"sending ack, %d",
|
2007-03-17 02:11:45 +03:00
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
2007-04-25 05:55:40 +04:00
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)), so_error);
|
|
|
|
}
|
|
|
|
|
2005-03-19 02:40:08 +03:00
|
|
|
mca_oob_tcp_peer_shutdown(peer);
|
2005-07-04 03:09:55 +04:00
|
|
|
opal_evtimer_add(&peer->peer_timer_event, &tv);
|
2004-08-03 01:24:00 +04:00
|
|
|
return;
|
|
|
|
} else if(so_error != 0) {
|
2006-09-22 19:51:11 +04:00
|
|
|
/* No need to worry about the return code here - we return regardless
|
|
|
|
at this point, and if an error did occur a message has already been
|
|
|
|
printed for the user */
|
|
|
|
mca_oob_tcp_peer_try_connect(peer);
|
|
|
|
return;
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
2004-07-14 01:03:03 +04:00
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
if(mca_oob_tcp_peer_send_connect_ack(peer, sd) == ORTE_SUCCESS) {
|
2004-07-13 02:46:57 +04:00
|
|
|
peer->peer_state = MCA_OOB_TCP_CONNECT_ACK;
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
/* Bug, FIXME: I don't know what I'm doing... */
|
|
|
|
if (sd == peer->peer_sd) {
|
|
|
|
opal_event_add (&peer->peer_recv_event, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sd == peer->peer6_sd) {
|
|
|
|
opal_event_add (&peer->peer6_recv_event, 0);
|
|
|
|
}
|
|
|
|
#else
|
2005-07-04 03:09:55 +04:00
|
|
|
opal_event_add(&peer->peer_recv_event, 0);
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
2004-07-13 02:46:57 +04:00
|
|
|
} else {
|
2005-07-04 03:31:27 +04:00
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_complete_connect: unable to send connect ack.",
|
2005-03-14 23:57:21 +03:00
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)));
|
2004-07-13 02:46:57 +04:00
|
|
|
mca_oob_tcp_peer_close(peer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Setup peer state to reflect that connection has been established,
|
|
|
|
* and start any pending sends.
|
|
|
|
*/
|
2007-04-25 05:55:40 +04:00
|
|
|
static void mca_oob_tcp_peer_connected(mca_oob_tcp_peer_t* peer, int sd)
|
2004-07-01 21:45:34 +04:00
|
|
|
{
|
2005-07-04 03:09:55 +04:00
|
|
|
opal_event_del(&peer->peer_timer_event);
|
2004-07-13 02:46:57 +04:00
|
|
|
peer->peer_state = MCA_OOB_TCP_CONNECTED;
|
|
|
|
peer->peer_retries = 0;
|
2005-07-03 20:22:16 +04:00
|
|
|
if(opal_list_get_size(&peer->peer_send_queue) > 0) {
|
2007-04-25 05:55:40 +04:00
|
|
|
if(NULL == peer->peer_send_msg) {
|
2004-07-13 02:46:57 +04:00
|
|
|
peer->peer_send_msg = (mca_oob_tcp_msg_t*)
|
2005-07-03 20:22:16 +04:00
|
|
|
opal_list_remove_first(&peer->peer_send_queue);
|
2007-04-25 05:55:40 +04:00
|
|
|
}
|
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
/* so we're connected. Let's close the other socket.
|
|
|
|
(some kind of magic --> might be a bug
|
|
|
|
*/
|
|
|
|
if (sd == peer->peer_sd) {
|
|
|
|
/* we've got an IPv4 connect; gently borrowed from
|
|
|
|
mca_oob_tcp_peer_shutdown. Refactor? Bug, FIXME
|
|
|
|
*/
|
|
|
|
if (peer->peer6_sd >= 0) {
|
|
|
|
opal_event_del(&peer->peer6_recv_event);
|
|
|
|
opal_event_del(&peer->peer6_send_event);
|
|
|
|
close(peer->peer6_sd);
|
|
|
|
peer->peer6_sd = -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (sd == peer->peer6_sd) {
|
|
|
|
/* IPv6 connect successful, so let's close
|
|
|
|
the IPv4 socket. Update the whole event structure.
|
|
|
|
*/
|
|
|
|
opal_event_del(&peer->peer_recv_event);
|
|
|
|
opal_event_del(&peer->peer_send_event);
|
|
|
|
peer->peer_recv_event = peer->peer6_recv_event;
|
|
|
|
peer->peer_send_event = peer->peer6_send_event;
|
|
|
|
close(peer->peer_sd);
|
|
|
|
peer->peer_sd = sd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2005-07-04 03:09:55 +04:00
|
|
|
opal_event_add(&peer->peer_send_event, 0);
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
|
|
|
}
|
2004-07-15 17:51:40 +04:00
|
|
|
|
2004-07-13 02:46:57 +04:00
|
|
|
/*
|
|
|
|
* Remove any event registrations associated with the socket
|
|
|
|
* and update the peer state to reflect the connection has
|
|
|
|
* been closed.
|
|
|
|
*/
|
2004-08-03 01:24:00 +04:00
|
|
|
void mca_oob_tcp_peer_close(mca_oob_tcp_peer_t* peer)
|
2004-07-13 02:46:57 +04:00
|
|
|
{
|
Fix a number of OOB issues:
* Remove the connect() timeout code, as it had some nasty race conditions
when connections were established as the trigger was firing. A better
solution has been found for the cluster where this was needed, so just
removing it was easiest.
* When a fatal error (too many connection failures) occurs, set an error
on messages in the queue even if there isn't an active message. The
first message to any peer will be queued without being active (and
so will all subsequent messages until the connection is established),
and the orteds will hang until that first message completes. So if
an orted can never contact it's peer, it will never exit and just sit
waiting for that message to complete.
* Cover an interesting RST condition in the connect code. A connection
can complete the three-way handshake, the connector can even send
some data, but the server side will drop the connection because it
can't move it from the half-connected to fully-connected state because
of space shortage in the listen backlog queue. This causes a RST to
be received first time that recv() is called, which will be when waiting
for the remote side of the OOB ack. In this case, transition the
connection back into a CLOSED state and try to connect again.
* Add levels of debugging, rather than all or nothing, each building on
the previous level. 0 (default) is hard errors. 1 is connection
error debugging info. 2 is all connection info. 3 is more state
info. 4 includes all message info.
* Add some hopefully useful comments
This commit was SVN r14261.
2007-04-08 02:33:30 +04:00
|
|
|
if(mca_oob_tcp_component.tcp_debug >= OOB_TCP_DEBUG_CONNECT) {
|
2005-07-04 03:31:27 +04:00
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_close(%p) sd %d state %d\n",
|
2005-03-14 23:57:21 +03:00
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
2007-01-31 07:24:56 +03:00
|
|
|
(void*)peer,
|
2004-09-02 03:07:40 +04:00
|
|
|
peer->peer_sd,
|
|
|
|
peer->peer_state);
|
|
|
|
}
|
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
if(mca_oob_tcp_component.tcp_debug >= OOB_TCP_DEBUG_CONNECT) {
|
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_close(%p) sd6 %d state %d\n",
|
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
|
|
|
(void*)peer,
|
|
|
|
peer->peer6_sd,
|
|
|
|
peer->peer_state);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-03-14 23:57:21 +03:00
|
|
|
/* if we lose the connection to the seed - abort */
|
Bring over the update to terminate orteds that are generated by a dynamic spawn such as comm_spawn. This introduces the concept of a job "family" - i.e., jobs that have a parent/child relationship. Comm_spawn'ed jobs have a parent (the one that spawned them). We track that relationship throughout the lineage - i.e., if a comm_spawned job in turn calls comm_spawn, then it has a parent (the one that spawned it) and a "root" job (the original job that started things).
Accordingly, there are new APIs to the name service to support the ability to get a job's parent, root, immediate children, and all its descendants. In addition, the terminate_job, terminate_orted, and signal_job APIs for the PLS have been modified to accept attributes that define the extent of their actions. For example, doing a "terminate_job" with an attribute of ORTE_NS_INCLUDE_DESCENDANTS will terminate the given jobid AND all jobs that descended from it.
I have tested this capability on a MacBook under rsh, Odin under SLURM, and LANL's Flash (bproc). It worked successfully on non-MPI jobs (both simple and including a spawn), and MPI jobs (again, both simple and with a spawn).
This commit was SVN r12597.
2006-11-14 22:34:59 +03:00
|
|
|
if(memcmp(&peer->peer_name,ORTE_PROC_MY_HNP,sizeof(orte_process_name_t)) == 0) {
|
2005-09-03 01:07:21 +04:00
|
|
|
/* If we are not already inside orte_finalize, then call abort */
|
|
|
|
if (ORTE_UNIVERSE_STATE_FINALIZE > orte_universe_info.state) {
|
2005-09-29 09:04:43 +04:00
|
|
|
/* Should free the peer lock before we abort so we don't
|
|
|
|
* get stuck in the orte_wait_kill when receiving messages in the
|
|
|
|
* tcp OOB. */
|
|
|
|
OPAL_THREAD_UNLOCK(&peer->peer_lock);
|
2006-09-15 01:29:51 +04:00
|
|
|
orte_errmgr.error_detected(1, "OOB: Connection to HNP lost", NULL);
|
2005-09-03 01:07:21 +04:00
|
|
|
}
|
2005-03-14 23:57:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
mca_oob_tcp_peer_shutdown(peer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mca_oob_tcp_peer_shutdown(mca_oob_tcp_peer_t* peer)
|
|
|
|
{
|
2004-08-28 05:15:19 +04:00
|
|
|
/* giving up and cleanup any pending messages */
|
|
|
|
if(peer->peer_retries++ > mca_oob_tcp_component.tcp_peer_retries) {
|
Fix a number of OOB issues:
* Remove the connect() timeout code, as it had some nasty race conditions
when connections were established as the trigger was firing. A better
solution has been found for the cluster where this was needed, so just
removing it was easiest.
* When a fatal error (too many connection failures) occurs, set an error
on messages in the queue even if there isn't an active message. The
first message to any peer will be queued without being active (and
so will all subsequent messages until the connection is established),
and the orteds will hang until that first message completes. So if
an orted can never contact it's peer, it will never exit and just sit
waiting for that message to complete.
* Cover an interesting RST condition in the connect code. A connection
can complete the three-way handshake, the connector can even send
some data, but the server side will drop the connection because it
can't move it from the half-connected to fully-connected state because
of space shortage in the listen backlog queue. This causes a RST to
be received first time that recv() is called, which will be when waiting
for the remote side of the OOB ack. In this case, transition the
connection back into a CLOSED state and try to connect again.
* Add levels of debugging, rather than all or nothing, each building on
the previous level. 0 (default) is hard errors. 1 is connection
error debugging info. 2 is all connection info. 3 is more state
info. 4 includes all message info.
* Add some hopefully useful comments
This commit was SVN r14261.
2007-04-08 02:33:30 +04:00
|
|
|
mca_oob_tcp_msg_t *msg;
|
|
|
|
|
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_shutdown: retries exceeded",
|
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)));
|
|
|
|
|
|
|
|
/* There are cases during the initial connection setup where
|
|
|
|
the peer_send_msg is NULL but there are things in the queue
|
|
|
|
-- handle that case */
|
|
|
|
if (NULL != (msg = peer->peer_send_msg)) {
|
|
|
|
msg->msg_complete = true;
|
2006-02-12 04:33:29 +03:00
|
|
|
msg->msg_rc = ORTE_ERR_UNREACH;
|
2004-08-28 05:15:19 +04:00
|
|
|
mca_oob_tcp_msg_complete(msg, &peer->peer_name);
|
|
|
|
}
|
|
|
|
peer->peer_send_msg = NULL;
|
Fix a number of OOB issues:
* Remove the connect() timeout code, as it had some nasty race conditions
when connections were established as the trigger was firing. A better
solution has been found for the cluster where this was needed, so just
removing it was easiest.
* When a fatal error (too many connection failures) occurs, set an error
on messages in the queue even if there isn't an active message. The
first message to any peer will be queued without being active (and
so will all subsequent messages until the connection is established),
and the orteds will hang until that first message completes. So if
an orted can never contact it's peer, it will never exit and just sit
waiting for that message to complete.
* Cover an interesting RST condition in the connect code. A connection
can complete the three-way handshake, the connector can even send
some data, but the server side will drop the connection because it
can't move it from the half-connected to fully-connected state because
of space shortage in the listen backlog queue. This causes a RST to
be received first time that recv() is called, which will be when waiting
for the remote side of the OOB ack. In this case, transition the
connection back into a CLOSED state and try to connect again.
* Add levels of debugging, rather than all or nothing, each building on
the previous level. 0 (default) is hard errors. 1 is connection
error debugging info. 2 is all connection info. 3 is more state
info. 4 includes all message info.
* Add some hopefully useful comments
This commit was SVN r14261.
2007-04-08 02:33:30 +04:00
|
|
|
while (NULL !=
|
|
|
|
(msg = (mca_oob_tcp_msg_t*)opal_list_remove_first(&peer->peer_send_queue))) {
|
|
|
|
msg->msg_complete = true;
|
|
|
|
msg->msg_rc = ORTE_ERR_UNREACH;
|
|
|
|
mca_oob_tcp_msg_complete(msg, &peer->peer_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We were unsuccessful in establishing a connection, and are
|
|
|
|
not likely to suddenly become successful, so abort the
|
|
|
|
whole thing */
|
|
|
|
peer->peer_state = MCA_OOB_TCP_FAILED;
|
2004-08-28 05:15:19 +04:00
|
|
|
}
|
|
|
|
|
2004-09-30 19:09:29 +04:00
|
|
|
if (peer->peer_sd >= 0) {
|
2005-07-04 03:09:55 +04:00
|
|
|
opal_event_del(&peer->peer_recv_event);
|
|
|
|
opal_event_del(&peer->peer_send_event);
|
2006-08-23 07:32:36 +04:00
|
|
|
CLOSE_THE_SOCKET(peer->peer_sd);
|
2004-07-13 02:46:57 +04:00
|
|
|
peer->peer_sd = -1;
|
2004-08-31 06:57:39 +04:00
|
|
|
}
|
2007-04-25 05:55:40 +04:00
|
|
|
|
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
if (peer->peer6_sd >= 0) {
|
|
|
|
opal_event_del(&peer->peer6_recv_event);
|
|
|
|
opal_event_del(&peer->peer6_send_event);
|
|
|
|
CLOSE_THE_SOCKET(peer->peer6_sd);
|
|
|
|
peer->peer6_sd = -1;
|
|
|
|
}
|
|
|
|
#endif
|
2004-09-02 03:07:40 +04:00
|
|
|
|
2005-07-04 03:09:55 +04:00
|
|
|
opal_event_del(&peer->peer_timer_event);
|
2004-07-13 02:46:57 +04:00
|
|
|
peer->peer_state = MCA_OOB_TCP_CLOSED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send the globally unique identifier for this process to a peer on
|
|
|
|
* a newly connected socket.
|
|
|
|
*/
|
2007-04-25 05:55:40 +04:00
|
|
|
static int mca_oob_tcp_peer_send_connect_ack(mca_oob_tcp_peer_t* peer, int sd)
|
2004-07-13 02:46:57 +04:00
|
|
|
{
|
2004-08-25 21:39:08 +04:00
|
|
|
/* send process identifier of self and peer - note that we may
|
|
|
|
* have assigned the peer a unique process name - if it came up
|
|
|
|
* without one.
|
|
|
|
*/
|
2005-05-05 20:31:40 +04:00
|
|
|
mca_oob_tcp_hdr_t hdr;
|
|
|
|
memset(&hdr,0,sizeof(hdr));
|
2005-03-14 23:57:21 +03:00
|
|
|
if (NULL == orte_process_info.my_name) { /* my name isn't defined yet */
|
Bring over the update to terminate orteds that are generated by a dynamic spawn such as comm_spawn. This introduces the concept of a job "family" - i.e., jobs that have a parent/child relationship. Comm_spawn'ed jobs have a parent (the one that spawned them). We track that relationship throughout the lineage - i.e., if a comm_spawned job in turn calls comm_spawn, then it has a parent (the one that spawned it) and a "root" job (the original job that started things).
Accordingly, there are new APIs to the name service to support the ability to get a job's parent, root, immediate children, and all its descendants. In addition, the terminate_job, terminate_orted, and signal_job APIs for the PLS have been modified to accept attributes that define the extent of their actions. For example, doing a "terminate_job" with an attribute of ORTE_NS_INCLUDE_DESCENDANTS will terminate the given jobid AND all jobs that descended from it.
I have tested this capability on a MacBook under rsh, Odin under SLURM, and LANL's Flash (bproc). It worked successfully on non-MPI jobs (both simple and including a spawn), and MPI jobs (again, both simple and with a spawn).
This commit was SVN r12597.
2006-11-14 22:34:59 +03:00
|
|
|
hdr.msg_src = *ORTE_NAME_INVALID;
|
2005-03-14 23:57:21 +03:00
|
|
|
} else {
|
2005-05-05 20:31:40 +04:00
|
|
|
hdr.msg_src = *(orte_process_info.my_name);
|
2005-03-14 23:57:21 +03:00
|
|
|
}
|
2005-05-05 20:31:40 +04:00
|
|
|
hdr.msg_dst = peer->peer_name;
|
|
|
|
hdr.msg_type = MCA_OOB_TCP_CONNECT;
|
|
|
|
MCA_OOB_TCP_HDR_HTON(&hdr);
|
2007-04-25 05:55:40 +04:00
|
|
|
if(mca_oob_tcp_peer_send_blocking(peer, sd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
|
2006-02-12 04:33:29 +03:00
|
|
|
return ORTE_ERR_UNREACH;
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
2006-02-12 04:33:29 +03:00
|
|
|
return ORTE_SUCCESS;
|
2004-07-01 21:45:34 +04:00
|
|
|
}
|
|
|
|
|
2004-07-13 02:46:57 +04:00
|
|
|
/*
|
|
|
|
* Receive the peers globally unique process identification from a newly
|
|
|
|
* connected socket and verify the expected response. If so, move the
|
|
|
|
* socket to a connected state.
|
|
|
|
*/
|
2007-04-25 05:55:40 +04:00
|
|
|
static int mca_oob_tcp_peer_recv_connect_ack(mca_oob_tcp_peer_t* peer, int sd)
|
2004-07-13 02:46:57 +04:00
|
|
|
{
|
2005-05-05 20:31:40 +04:00
|
|
|
mca_oob_tcp_hdr_t hdr;
|
2007-04-25 05:55:40 +04:00
|
|
|
if((mca_oob_tcp_peer_recv_blocking(peer, sd, &hdr, sizeof(hdr))) != sizeof(hdr)) {
|
Fix a number of OOB issues:
* Remove the connect() timeout code, as it had some nasty race conditions
when connections were established as the trigger was firing. A better
solution has been found for the cluster where this was needed, so just
removing it was easiest.
* When a fatal error (too many connection failures) occurs, set an error
on messages in the queue even if there isn't an active message. The
first message to any peer will be queued without being active (and
so will all subsequent messages until the connection is established),
and the orteds will hang until that first message completes. So if
an orted can never contact it's peer, it will never exit and just sit
waiting for that message to complete.
* Cover an interesting RST condition in the connect code. A connection
can complete the three-way handshake, the connector can even send
some data, but the server side will drop the connection because it
can't move it from the half-connected to fully-connected state because
of space shortage in the listen backlog queue. This causes a RST to
be received first time that recv() is called, which will be when waiting
for the remote side of the OOB ack. In this case, transition the
connection back into a CLOSED state and try to connect again.
* Add levels of debugging, rather than all or nothing, each building on
the previous level. 0 (default) is hard errors. 1 is connection
error debugging info. 2 is all connection info. 3 is more state
info. 4 includes all message info.
* Add some hopefully useful comments
This commit was SVN r14261.
2007-04-08 02:33:30 +04:00
|
|
|
/* If the peer state is still CONNECT_ACK, that indicates that
|
|
|
|
the error was a reset from the remote host because the
|
|
|
|
connection was not able to be fully established. In that
|
|
|
|
case, Clean up the connection and give it another go. */
|
|
|
|
if (peer->peer_state == MCA_OOB_TCP_CONNECT_ACK) {
|
2007-04-08 03:00:57 +04:00
|
|
|
struct timeval tv = { 1,0 };
|
Fix a number of OOB issues:
* Remove the connect() timeout code, as it had some nasty race conditions
when connections were established as the trigger was firing. A better
solution has been found for the cluster where this was needed, so just
removing it was easiest.
* When a fatal error (too many connection failures) occurs, set an error
on messages in the queue even if there isn't an active message. The
first message to any peer will be queued without being active (and
so will all subsequent messages until the connection is established),
and the orteds will hang until that first message completes. So if
an orted can never contact it's peer, it will never exit and just sit
waiting for that message to complete.
* Cover an interesting RST condition in the connect code. A connection
can complete the three-way handshake, the connector can even send
some data, but the server side will drop the connection because it
can't move it from the half-connected to fully-connected state because
of space shortage in the listen backlog queue. This causes a RST to
be received first time that recv() is called, which will be when waiting
for the remote side of the OOB ack. In this case, transition the
connection back into a CLOSED state and try to connect again.
* Add levels of debugging, rather than all or nothing, each building on
the previous level. 0 (default) is hard errors. 1 is connection
error debugging info. 2 is all connection info. 3 is more state
info. 4 includes all message info.
* Add some hopefully useful comments
This commit was SVN r14261.
2007-04-08 02:33:30 +04:00
|
|
|
if (mca_oob_tcp_component.tcp_debug >= OOB_TCP_DEBUG_CONNECT) {
|
|
|
|
opal_output(0,
|
|
|
|
"[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_recv_connect_ack "
|
|
|
|
"connect failed during receive. Restarting (%s).",
|
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
|
|
|
strerror(opal_socket_errno));
|
|
|
|
}
|
|
|
|
opal_event_del(&peer->peer_recv_event);
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
opal_event_del(&peer->peer6_recv_event);
|
|
|
|
#endif
|
Fix a number of OOB issues:
* Remove the connect() timeout code, as it had some nasty race conditions
when connections were established as the trigger was firing. A better
solution has been found for the cluster where this was needed, so just
removing it was easiest.
* When a fatal error (too many connection failures) occurs, set an error
on messages in the queue even if there isn't an active message. The
first message to any peer will be queued without being active (and
so will all subsequent messages until the connection is established),
and the orteds will hang until that first message completes. So if
an orted can never contact it's peer, it will never exit and just sit
waiting for that message to complete.
* Cover an interesting RST condition in the connect code. A connection
can complete the three-way handshake, the connector can even send
some data, but the server side will drop the connection because it
can't move it from the half-connected to fully-connected state because
of space shortage in the listen backlog queue. This causes a RST to
be received first time that recv() is called, which will be when waiting
for the remote side of the OOB ack. In this case, transition the
connection back into a CLOSED state and try to connect again.
* Add levels of debugging, rather than all or nothing, each building on
the previous level. 0 (default) is hard errors. 1 is connection
error debugging info. 2 is all connection info. 3 is more state
info. 4 includes all message info.
* Add some hopefully useful comments
This commit was SVN r14261.
2007-04-08 02:33:30 +04:00
|
|
|
mca_oob_tcp_peer_shutdown(peer);
|
|
|
|
opal_evtimer_add(&peer->peer_timer_event, &tv);
|
|
|
|
return ORTE_SUCCESS;
|
|
|
|
} else {
|
|
|
|
mca_oob_tcp_peer_close(peer);
|
|
|
|
return ORTE_ERR_UNREACH;
|
|
|
|
}
|
2005-05-05 20:31:40 +04:00
|
|
|
}
|
|
|
|
MCA_OOB_TCP_HDR_NTOH(&hdr);
|
|
|
|
if(hdr.msg_type != MCA_OOB_TCP_CONNECT) {
|
Fix a number of OOB issues:
* Remove the connect() timeout code, as it had some nasty race conditions
when connections were established as the trigger was firing. A better
solution has been found for the cluster where this was needed, so just
removing it was easiest.
* When a fatal error (too many connection failures) occurs, set an error
on messages in the queue even if there isn't an active message. The
first message to any peer will be queued without being active (and
so will all subsequent messages until the connection is established),
and the orteds will hang until that first message completes. So if
an orted can never contact it's peer, it will never exit and just sit
waiting for that message to complete.
* Cover an interesting RST condition in the connect code. A connection
can complete the three-way handshake, the connector can even send
some data, but the server side will drop the connection because it
can't move it from the half-connected to fully-connected state because
of space shortage in the listen backlog queue. This causes a RST to
be received first time that recv() is called, which will be when waiting
for the remote side of the OOB ack. In this case, transition the
connection back into a CLOSED state and try to connect again.
* Add levels of debugging, rather than all or nothing, each building on
the previous level. 0 (default) is hard errors. 1 is connection
error debugging info. 2 is all connection info. 3 is more state
info. 4 includes all message info.
* Add some hopefully useful comments
This commit was SVN r14261.
2007-04-08 02:33:30 +04:00
|
|
|
opal_output(0, "mca_oob_tcp_peer_recv_connect_ack: invalid header type: %d\n",
|
|
|
|
hdr.msg_type);
|
2004-09-29 21:18:14 +04:00
|
|
|
mca_oob_tcp_peer_close(peer);
|
2006-02-12 04:33:29 +03:00
|
|
|
return ORTE_ERR_UNREACH;
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
Fix a number of OOB issues:
* Remove the connect() timeout code, as it had some nasty race conditions
when connections were established as the trigger was firing. A better
solution has been found for the cluster where this was needed, so just
removing it was easiest.
* When a fatal error (too many connection failures) occurs, set an error
on messages in the queue even if there isn't an active message. The
first message to any peer will be queued without being active (and
so will all subsequent messages until the connection is established),
and the orteds will hang until that first message completes. So if
an orted can never contact it's peer, it will never exit and just sit
waiting for that message to complete.
* Cover an interesting RST condition in the connect code. A connection
can complete the three-way handshake, the connector can even send
some data, but the server side will drop the connection because it
can't move it from the half-connected to fully-connected state because
of space shortage in the listen backlog queue. This causes a RST to
be received first time that recv() is called, which will be when waiting
for the remote side of the OOB ack. In this case, transition the
connection back into a CLOSED state and try to connect again.
* Add levels of debugging, rather than all or nothing, each building on
the previous level. 0 (default) is hard errors. 1 is connection
error debugging info. 2 is all connection info. 3 is more state
info. 4 includes all message info.
* Add some hopefully useful comments
This commit was SVN r14261.
2007-04-08 02:33:30 +04:00
|
|
|
|
2004-08-25 21:39:08 +04:00
|
|
|
/* compare the peers name to the expected value */
|
2005-05-05 20:31:40 +04:00
|
|
|
if(memcmp(&peer->peer_name, &hdr.msg_src, sizeof(orte_process_name_t)) != 0) {
|
2005-07-04 03:31:27 +04:00
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_recv_connect_ack: "
|
2007-01-30 23:56:31 +03:00
|
|
|
"received unexpected process identifier [%ld,%ld,%ld]\n",
|
2005-03-14 23:57:21 +03:00
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
2005-05-05 20:31:40 +04:00
|
|
|
ORTE_NAME_ARGS(&(hdr.msg_src)));
|
2004-07-13 02:46:57 +04:00
|
|
|
mca_oob_tcp_peer_close(peer);
|
2006-02-12 04:33:29 +03:00
|
|
|
return ORTE_ERR_UNREACH;
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
|
|
|
|
Fix a number of OOB issues:
* Remove the connect() timeout code, as it had some nasty race conditions
when connections were established as the trigger was firing. A better
solution has been found for the cluster where this was needed, so just
removing it was easiest.
* When a fatal error (too many connection failures) occurs, set an error
on messages in the queue even if there isn't an active message. The
first message to any peer will be queued without being active (and
so will all subsequent messages until the connection is established),
and the orteds will hang until that first message completes. So if
an orted can never contact it's peer, it will never exit and just sit
waiting for that message to complete.
* Cover an interesting RST condition in the connect code. A connection
can complete the three-way handshake, the connector can even send
some data, but the server side will drop the connection because it
can't move it from the half-connected to fully-connected state because
of space shortage in the listen backlog queue. This causes a RST to
be received first time that recv() is called, which will be when waiting
for the remote side of the OOB ack. In this case, transition the
connection back into a CLOSED state and try to connect again.
* Add levels of debugging, rather than all or nothing, each building on
the previous level. 0 (default) is hard errors. 1 is connection
error debugging info. 2 is all connection info. 3 is more state
info. 4 includes all message info.
* Add some hopefully useful comments
This commit was SVN r14261.
2007-04-08 02:33:30 +04:00
|
|
|
/* if we have an invalid name or do not have one assigned at all -
|
|
|
|
* use the name returned by the peer. This needs to be a LITERAL
|
|
|
|
* comparison - we do NOT want wildcard values to return EQUAL
|
Bring over the update to terminate orteds that are generated by a dynamic spawn such as comm_spawn. This introduces the concept of a job "family" - i.e., jobs that have a parent/child relationship. Comm_spawn'ed jobs have a parent (the one that spawned them). We track that relationship throughout the lineage - i.e., if a comm_spawned job in turn calls comm_spawn, then it has a parent (the one that spawned it) and a "root" job (the original job that started things).
Accordingly, there are new APIs to the name service to support the ability to get a job's parent, root, immediate children, and all its descendants. In addition, the terminate_job, terminate_orted, and signal_job APIs for the PLS have been modified to accept attributes that define the extent of their actions. For example, doing a "terminate_job" with an attribute of ORTE_NS_INCLUDE_DESCENDANTS will terminate the given jobid AND all jobs that descended from it.
I have tested this capability on a MacBook under rsh, Odin under SLURM, and LANL's Flash (bproc). It worked successfully on non-MPI jobs (both simple and including a spawn), and MPI jobs (again, both simple and with a spawn).
This commit was SVN r12597.
2006-11-14 22:34:59 +03:00
|
|
|
*/
|
2005-05-23 20:23:11 +04:00
|
|
|
if(orte_process_info.my_name == NULL) {
|
|
|
|
orte_ns.create_process_name(&orte_process_info.my_name,
|
|
|
|
hdr.msg_dst.cellid, hdr.msg_dst.jobid, hdr.msg_dst.vpid);
|
Bring over the update to terminate orteds that are generated by a dynamic spawn such as comm_spawn. This introduces the concept of a job "family" - i.e., jobs that have a parent/child relationship. Comm_spawn'ed jobs have a parent (the one that spawned them). We track that relationship throughout the lineage - i.e., if a comm_spawned job in turn calls comm_spawn, then it has a parent (the one that spawned it) and a "root" job (the original job that started things).
Accordingly, there are new APIs to the name service to support the ability to get a job's parent, root, immediate children, and all its descendants. In addition, the terminate_job, terminate_orted, and signal_job APIs for the PLS have been modified to accept attributes that define the extent of their actions. For example, doing a "terminate_job" with an attribute of ORTE_NS_INCLUDE_DESCENDANTS will terminate the given jobid AND all jobs that descended from it.
I have tested this capability on a MacBook under rsh, Odin under SLURM, and LANL's Flash (bproc). It worked successfully on non-MPI jobs (both simple and including a spawn), and MPI jobs (again, both simple and with a spawn).
This commit was SVN r12597.
2006-11-14 22:34:59 +03:00
|
|
|
} else if (orte_ns.compare_fields(ORTE_NS_CMP_ALL, orte_process_info.my_name, ORTE_NAME_INVALID) == ORTE_EQUAL) {
|
2005-05-05 20:31:40 +04:00
|
|
|
*orte_process_info.my_name = hdr.msg_dst;
|
2004-08-25 21:39:08 +04:00
|
|
|
}
|
|
|
|
|
2004-07-13 02:46:57 +04:00
|
|
|
/* connected */
|
2007-04-25 05:55:40 +04:00
|
|
|
mca_oob_tcp_peer_connected(peer, sd);
|
Fix a number of OOB issues:
* Remove the connect() timeout code, as it had some nasty race conditions
when connections were established as the trigger was firing. A better
solution has been found for the cluster where this was needed, so just
removing it was easiest.
* When a fatal error (too many connection failures) occurs, set an error
on messages in the queue even if there isn't an active message. The
first message to any peer will be queued without being active (and
so will all subsequent messages until the connection is established),
and the orteds will hang until that first message completes. So if
an orted can never contact it's peer, it will never exit and just sit
waiting for that message to complete.
* Cover an interesting RST condition in the connect code. A connection
can complete the three-way handshake, the connector can even send
some data, but the server side will drop the connection because it
can't move it from the half-connected to fully-connected state because
of space shortage in the listen backlog queue. This causes a RST to
be received first time that recv() is called, which will be when waiting
for the remote side of the OOB ack. In this case, transition the
connection back into a CLOSED state and try to connect again.
* Add levels of debugging, rather than all or nothing, each building on
the previous level. 0 (default) is hard errors. 1 is connection
error debugging info. 2 is all connection info. 3 is more state
info. 4 includes all message info.
* Add some hopefully useful comments
This commit was SVN r14261.
2007-04-08 02:33:30 +04:00
|
|
|
if(mca_oob_tcp_component.tcp_debug >= OOB_TCP_DEBUG_CONNECT) {
|
2004-09-02 03:07:40 +04:00
|
|
|
mca_oob_tcp_peer_dump(peer, "connected");
|
|
|
|
}
|
2006-02-12 04:33:29 +03:00
|
|
|
return ORTE_SUCCESS;
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
2004-07-15 17:51:40 +04:00
|
|
|
|
2004-09-29 21:18:14 +04:00
|
|
|
|
2004-07-13 02:46:57 +04:00
|
|
|
/*
|
|
|
|
* A blocking recv on a non-blocking socket. Used to receive the small amount of connection
|
|
|
|
* information that identifies the peers endpoint.
|
|
|
|
*/
|
2007-04-25 05:55:40 +04:00
|
|
|
static int mca_oob_tcp_peer_recv_blocking(mca_oob_tcp_peer_t* peer, int sd, void* data, size_t size)
|
2004-07-13 02:46:57 +04:00
|
|
|
{
|
|
|
|
unsigned char* ptr = (unsigned char*)data;
|
|
|
|
size_t cnt = 0;
|
|
|
|
while(cnt < size) {
|
2007-04-25 05:55:40 +04:00
|
|
|
int retval = recv(sd,(char *)ptr+cnt, size-cnt, 0);
|
2004-07-13 02:46:57 +04:00
|
|
|
|
|
|
|
/* remote closed connection */
|
|
|
|
if(retval == 0) {
|
Fix a number of OOB issues:
* Remove the connect() timeout code, as it had some nasty race conditions
when connections were established as the trigger was firing. A better
solution has been found for the cluster where this was needed, so just
removing it was easiest.
* When a fatal error (too many connection failures) occurs, set an error
on messages in the queue even if there isn't an active message. The
first message to any peer will be queued without being active (and
so will all subsequent messages until the connection is established),
and the orteds will hang until that first message completes. So if
an orted can never contact it's peer, it will never exit and just sit
waiting for that message to complete.
* Cover an interesting RST condition in the connect code. A connection
can complete the three-way handshake, the connector can even send
some data, but the server side will drop the connection because it
can't move it from the half-connected to fully-connected state because
of space shortage in the listen backlog queue. This causes a RST to
be received first time that recv() is called, which will be when waiting
for the remote side of the OOB ack. In this case, transition the
connection back into a CLOSED state and try to connect again.
* Add levels of debugging, rather than all or nothing, each building on
the previous level. 0 (default) is hard errors. 1 is connection
error debugging info. 2 is all connection info. 3 is more state
info. 4 includes all message info.
* Add some hopefully useful comments
This commit was SVN r14261.
2007-04-08 02:33:30 +04:00
|
|
|
if(mca_oob_tcp_component.tcp_debug >= OOB_TCP_DEBUG_INFO) {
|
2005-07-04 03:31:27 +04:00
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_recv_blocking: "
|
2004-09-08 21:02:24 +04:00
|
|
|
"peer closed connection: peer state %d",
|
2005-03-14 23:57:21 +03:00
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
2004-09-08 21:02:24 +04:00
|
|
|
peer->peer_state);
|
|
|
|
}
|
2004-07-13 02:46:57 +04:00
|
|
|
mca_oob_tcp_peer_close(peer);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* socket is non-blocking so handle errors */
|
|
|
|
if(retval < 0) {
|
Fix a number of OOB issues:
* Remove the connect() timeout code, as it had some nasty race conditions
when connections were established as the trigger was firing. A better
solution has been found for the cluster where this was needed, so just
removing it was easiest.
* When a fatal error (too many connection failures) occurs, set an error
on messages in the queue even if there isn't an active message. The
first message to any peer will be queued without being active (and
so will all subsequent messages until the connection is established),
and the orteds will hang until that first message completes. So if
an orted can never contact it's peer, it will never exit and just sit
waiting for that message to complete.
* Cover an interesting RST condition in the connect code. A connection
can complete the three-way handshake, the connector can even send
some data, but the server side will drop the connection because it
can't move it from the half-connected to fully-connected state because
of space shortage in the listen backlog queue. This causes a RST to
be received first time that recv() is called, which will be when waiting
for the remote side of the OOB ack. In this case, transition the
connection back into a CLOSED state and try to connect again.
* Add levels of debugging, rather than all or nothing, each building on
the previous level. 0 (default) is hard errors. 1 is connection
error debugging info. 2 is all connection info. 3 is more state
info. 4 includes all message info.
* Add some hopefully useful comments
This commit was SVN r14261.
2007-04-08 02:33:30 +04:00
|
|
|
if(opal_socket_errno != EINTR &&
|
|
|
|
opal_socket_errno != EAGAIN &&
|
|
|
|
opal_socket_errno != EWOULDBLOCK) {
|
|
|
|
if (peer->peer_state == MCA_OOB_TCP_CONNECT_ACK) {
|
|
|
|
/* If we overflow the listen backlog, it's
|
|
|
|
possible that even though we finished the three
|
|
|
|
way handshake, the remote host was unable to
|
|
|
|
transition the connection from half connected
|
|
|
|
(received the initial SYN) to fully connected
|
|
|
|
(in the listen backlog). We likely won't see
|
|
|
|
the failure until we try to receive, due to
|
|
|
|
timing and the like. The first thing we'll get
|
|
|
|
in that case is a RST packet, which receive
|
|
|
|
will turn into a connection reset by peer
|
|
|
|
errno. In that case, leave the socket in
|
|
|
|
CONNECT_ACK and propogate the error up to
|
|
|
|
recv_connect_ack, who will try to establish the
|
|
|
|
connection again */
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
opal_output(0,
|
|
|
|
"[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_recv_blocking: "
|
|
|
|
"recv() failed: %s (%d)\n",
|
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
|
|
|
strerror(errno),
|
|
|
|
errno);
|
|
|
|
mca_oob_tcp_peer_close(peer);
|
|
|
|
return -1;
|
|
|
|
}
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
cnt += retval;
|
|
|
|
}
|
|
|
|
return cnt;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A blocking send on a non-blocking socket. Used to send the small amount of connection
|
|
|
|
* information that identifies the peers endpoint.
|
|
|
|
*/
|
2007-04-25 05:55:40 +04:00
|
|
|
static int mca_oob_tcp_peer_send_blocking(mca_oob_tcp_peer_t* peer, int sd, void* data, size_t size)
|
2004-07-13 02:46:57 +04:00
|
|
|
{
|
|
|
|
unsigned char* ptr = (unsigned char*)data;
|
|
|
|
size_t cnt = 0;
|
|
|
|
while(cnt < size) {
|
2007-04-25 05:55:40 +04:00
|
|
|
int retval = send(sd, (char *)ptr+cnt, size-cnt, 0);
|
2004-07-13 02:46:57 +04:00
|
|
|
if(retval < 0) {
|
2006-08-15 00:14:44 +04:00
|
|
|
if(opal_socket_errno != EINTR && opal_socket_errno != EAGAIN && opal_socket_errno != EWOULDBLOCK) {
|
2006-12-14 21:20:43 +03:00
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_send_blocking: send() failed: %s (%d)\n",
|
2005-03-14 23:57:21 +03:00
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
2006-12-14 21:20:43 +03:00
|
|
|
strerror(opal_socket_errno),
|
2006-08-15 00:14:44 +04:00
|
|
|
opal_socket_errno);
|
2004-07-13 02:46:57 +04:00
|
|
|
mca_oob_tcp_peer_close(peer);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
cnt += retval;
|
|
|
|
}
|
|
|
|
return cnt;
|
|
|
|
}
|
|
|
|
|
2004-08-03 01:24:00 +04:00
|
|
|
|
2004-09-02 03:07:40 +04:00
|
|
|
int mca_oob_tcp_peer_send_ident(mca_oob_tcp_peer_t* peer)
|
|
|
|
{
|
|
|
|
mca_oob_tcp_hdr_t hdr;
|
|
|
|
if(peer->peer_state != MCA_OOB_TCP_CONNECTED)
|
2006-02-12 04:33:29 +03:00
|
|
|
return ORTE_SUCCESS;
|
2005-03-14 23:57:21 +03:00
|
|
|
hdr.msg_src = *orte_process_info.my_name;
|
2004-09-02 03:07:40 +04:00
|
|
|
hdr.msg_dst = peer->peer_name;
|
|
|
|
hdr.msg_type = MCA_OOB_TCP_IDENT;
|
|
|
|
hdr.msg_size = 0;
|
|
|
|
hdr.msg_tag = 0;
|
|
|
|
MCA_OOB_TCP_HDR_HTON(&hdr);
|
2007-04-25 05:55:40 +04:00
|
|
|
if(mca_oob_tcp_peer_send_blocking(peer, peer->peer_sd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
|
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
if (-1 < peer->peer6_sd) {
|
|
|
|
if(mca_oob_tcp_peer_send_blocking(peer, peer->peer6_sd,
|
|
|
|
&hdr, sizeof(hdr)) != sizeof(hdr)) {
|
|
|
|
return ORTE_ERR_UNREACH;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
2006-02-12 04:33:29 +03:00
|
|
|
return ORTE_ERR_UNREACH;
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
|
|
|
}
|
2006-02-12 04:33:29 +03:00
|
|
|
return ORTE_SUCCESS;
|
2004-09-02 03:07:40 +04:00
|
|
|
}
|
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
|
2004-11-21 20:20:42 +03:00
|
|
|
/* static void mca_oob_tcp_peer_recv_ident(mca_oob_tcp_peer_t* peer, mca_oob_tcp_hdr_t* hdr) */
|
|
|
|
/* { */
|
2005-07-04 02:45:48 +04:00
|
|
|
/* OPAL_THREAD_LOCK(&mca_oob_tcp_component.tcp_lock); */
|
2004-11-21 20:20:42 +03:00
|
|
|
/* ompi_rb_tree_delete(&mca_oob_tcp_component.tcp_peer_tree, &peer->peer_name); */
|
|
|
|
/* peer->peer_name = hdr->msg_src; */
|
|
|
|
/* ompi_rb_tree_insert(&mca_oob_tcp_component.tcp_peer_tree, &peer->peer_name, peer); */
|
2005-07-04 02:45:48 +04:00
|
|
|
/* OPAL_THREAD_UNLOCK(&mca_oob_tcp_component.tcp_lock); */
|
2004-11-21 20:20:42 +03:00
|
|
|
/* } */
|
2004-09-02 03:07:40 +04:00
|
|
|
|
|
|
|
|
2004-08-03 01:24:00 +04:00
|
|
|
/*
|
|
|
|
* Dispatch to the appropriate action routine based on the state
|
|
|
|
* of the connection with the peer.
|
|
|
|
*/
|
2004-07-13 02:46:57 +04:00
|
|
|
|
|
|
|
static void mca_oob_tcp_peer_recv_handler(int sd, short flags, void* user)
|
|
|
|
{
|
2004-10-28 22:13:43 +04:00
|
|
|
mca_oob_tcp_peer_t* peer = (mca_oob_tcp_peer_t *)user;
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_LOCK(&peer->peer_lock);
|
2004-07-13 02:46:57 +04:00
|
|
|
switch(peer->peer_state) {
|
2004-08-03 01:24:00 +04:00
|
|
|
case MCA_OOB_TCP_CONNECT_ACK:
|
2004-07-13 02:46:57 +04:00
|
|
|
{
|
2007-04-25 05:55:40 +04:00
|
|
|
mca_oob_tcp_peer_recv_connect_ack(peer, sd);
|
2004-08-03 01:24:00 +04:00
|
|
|
break;
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
2004-08-03 01:24:00 +04:00
|
|
|
case MCA_OOB_TCP_CONNECTED:
|
2004-07-13 02:46:57 +04:00
|
|
|
{
|
Not as bad as this all may look. Tim and I made a significant change to the way we handle the startup of the oob, the seed, etc. We have made it backwards-compatible so that mpirun2 and singleton operations remain working. We had to adjust the name server and gpr as well, plus the process_info structure.
This also includes a checkpoint update to openmpi.c and ompid.c. I have re-enabled the ompid compile.
This latter raises an important point. The trunk compiles the programs like ompid just fine under Linux. It also does just fine for OSX under the dynamic libraries. However, we are seeing errors when compiling under OSX for the static case - the linker seems to have trouble resolving some variable names, even though linker diagnostics show the variables as being defined. Thus, a warning to Mac users that you may have to locally turn things off if you are trying to do static compiles. We ask, however, that you don't commit those changes that turn things off for everyone else - instead, let's try to figure out why the static compile is having a problem, and let everyone else continue to work.
Thanks
Ralph
This commit was SVN r2534.
2004-09-08 07:59:06 +04:00
|
|
|
/* allocate a new message and setup for recv */
|
2004-08-03 01:24:00 +04:00
|
|
|
if(NULL == peer->peer_recv_msg) {
|
Not as bad as this all may look. Tim and I made a significant change to the way we handle the startup of the oob, the seed, etc. We have made it backwards-compatible so that mpirun2 and singleton operations remain working. We had to adjust the name server and gpr as well, plus the process_info structure.
This also includes a checkpoint update to openmpi.c and ompid.c. I have re-enabled the ompid compile.
This latter raises an important point. The trunk compiles the programs like ompid just fine under Linux. It also does just fine for OSX under the dynamic libraries. However, we are seeing errors when compiling under OSX for the static case - the linker seems to have trouble resolving some variable names, even though linker diagnostics show the variables as being defined. Thus, a warning to Mac users that you may have to locally turn things off if you are trying to do static compiles. We ask, however, that you don't commit those changes that turn things off for everyone else - instead, let's try to figure out why the static compile is having a problem, and let everyone else continue to work.
Thanks
Ralph
This commit was SVN r2534.
2004-09-08 07:59:06 +04:00
|
|
|
int rc;
|
|
|
|
mca_oob_tcp_msg_t* msg;
|
|
|
|
MCA_OOB_TCP_MSG_ALLOC(msg, rc);
|
|
|
|
if(NULL == msg) {
|
2005-07-04 03:31:27 +04:00
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_recv_handler: unable to allocate recv message\n",
|
2005-03-14 23:57:21 +03:00
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)));
|
Not as bad as this all may look. Tim and I made a significant change to the way we handle the startup of the oob, the seed, etc. We have made it backwards-compatible so that mpirun2 and singleton operations remain working. We had to adjust the name server and gpr as well, plus the process_info structure.
This also includes a checkpoint update to openmpi.c and ompid.c. I have re-enabled the ompid compile.
This latter raises an important point. The trunk compiles the programs like ompid just fine under Linux. It also does just fine for OSX under the dynamic libraries. However, we are seeing errors when compiling under OSX for the static case - the linker seems to have trouble resolving some variable names, even though linker diagnostics show the variables as being defined. Thus, a warning to Mac users that you may have to locally turn things off if you are trying to do static compiles. We ask, however, that you don't commit those changes that turn things off for everyone else - instead, let's try to figure out why the static compile is having a problem, and let everyone else continue to work.
Thanks
Ralph
This commit was SVN r2534.
2004-09-08 07:59:06 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
msg->msg_type = MCA_OOB_TCP_UNEXPECTED;
|
|
|
|
msg->msg_rc = 0;
|
|
|
|
msg->msg_flags = 0;
|
|
|
|
msg->msg_peer = peer->peer_name;
|
|
|
|
msg->msg_rwiov = mca_oob_tcp_msg_iov_alloc(msg,2);
|
|
|
|
msg->msg_rwbuf = NULL;
|
|
|
|
msg->msg_rwcnt = msg->msg_rwnum = 1;
|
|
|
|
msg->msg_rwptr = msg->msg_rwiov;
|
2005-01-26 03:20:35 +03:00
|
|
|
msg->msg_rwiov[0].iov_base = (ompi_iov_base_ptr_t)&msg->msg_hdr;
|
Not as bad as this all may look. Tim and I made a significant change to the way we handle the startup of the oob, the seed, etc. We have made it backwards-compatible so that mpirun2 and singleton operations remain working. We had to adjust the name server and gpr as well, plus the process_info structure.
This also includes a checkpoint update to openmpi.c and ompid.c. I have re-enabled the ompid compile.
This latter raises an important point. The trunk compiles the programs like ompid just fine under Linux. It also does just fine for OSX under the dynamic libraries. However, we are seeing errors when compiling under OSX for the static case - the linker seems to have trouble resolving some variable names, even though linker diagnostics show the variables as being defined. Thus, a warning to Mac users that you may have to locally turn things off if you are trying to do static compiles. We ask, however, that you don't commit those changes that turn things off for everyone else - instead, let's try to figure out why the static compile is having a problem, and let everyone else continue to work.
Thanks
Ralph
This commit was SVN r2534.
2004-09-08 07:59:06 +04:00
|
|
|
msg->msg_rwiov[0].iov_len = sizeof(msg->msg_hdr);
|
|
|
|
peer->peer_recv_msg = msg;
|
2004-08-28 05:15:19 +04:00
|
|
|
}
|
Not as bad as this all may look. Tim and I made a significant change to the way we handle the startup of the oob, the seed, etc. We have made it backwards-compatible so that mpirun2 and singleton operations remain working. We had to adjust the name server and gpr as well, plus the process_info structure.
This also includes a checkpoint update to openmpi.c and ompid.c. I have re-enabled the ompid compile.
This latter raises an important point. The trunk compiles the programs like ompid just fine under Linux. It also does just fine for OSX under the dynamic libraries. However, we are seeing errors when compiling under OSX for the static case - the linker seems to have trouble resolving some variable names, even though linker diagnostics show the variables as being defined. Thus, a warning to Mac users that you may have to locally turn things off if you are trying to do static compiles. We ask, however, that you don't commit those changes that turn things off for everyone else - instead, let's try to figure out why the static compile is having a problem, and let everyone else continue to work.
Thanks
Ralph
This commit was SVN r2534.
2004-09-08 07:59:06 +04:00
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
if (peer->peer_recv_msg &&
|
2004-08-28 05:15:19 +04:00
|
|
|
mca_oob_tcp_msg_recv_handler(peer->peer_recv_msg, peer)) {
|
|
|
|
mca_oob_tcp_msg_t* msg = peer->peer_recv_msg;
|
2004-08-03 01:24:00 +04:00
|
|
|
peer->peer_recv_msg = NULL;
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_UNLOCK(&peer->peer_lock);
|
Not as bad as this all may look. Tim and I made a significant change to the way we handle the startup of the oob, the seed, etc. We have made it backwards-compatible so that mpirun2 and singleton operations remain working. We had to adjust the name server and gpr as well, plus the process_info structure.
This also includes a checkpoint update to openmpi.c and ompid.c. I have re-enabled the ompid compile.
This latter raises an important point. The trunk compiles the programs like ompid just fine under Linux. It also does just fine for OSX under the dynamic libraries. However, we are seeing errors when compiling under OSX for the static case - the linker seems to have trouble resolving some variable names, even though linker diagnostics show the variables as being defined. Thus, a warning to Mac users that you may have to locally turn things off if you are trying to do static compiles. We ask, however, that you don't commit those changes that turn things off for everyone else - instead, let's try to figure out why the static compile is having a problem, and let everyone else continue to work.
Thanks
Ralph
This commit was SVN r2534.
2004-09-08 07:59:06 +04:00
|
|
|
mca_oob_tcp_msg_recv_complete(msg, peer);
|
2004-08-28 05:15:19 +04:00
|
|
|
return;
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
2004-08-03 01:24:00 +04:00
|
|
|
break;
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
2004-08-03 01:24:00 +04:00
|
|
|
default:
|
2004-07-13 02:46:57 +04:00
|
|
|
{
|
2005-07-04 03:31:27 +04:00
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_recv_handler: invalid socket state(%d)",
|
2005-03-14 23:57:21 +03:00
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
2004-08-31 06:57:39 +04:00
|
|
|
peer->peer_state);
|
2004-08-03 01:24:00 +04:00
|
|
|
mca_oob_tcp_peer_close(peer);
|
|
|
|
break;
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
|
|
|
}
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_UNLOCK(&peer->peer_lock);
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A file descriptor is available/ready for send. Check the state
|
|
|
|
* of the socket and take the appropriate action.
|
|
|
|
*/
|
|
|
|
static void mca_oob_tcp_peer_send_handler(int sd, short flags, void* user)
|
|
|
|
{
|
2004-10-28 22:13:43 +04:00
|
|
|
mca_oob_tcp_peer_t* peer = (mca_oob_tcp_peer_t *)user;
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_LOCK(&peer->peer_lock);
|
2004-07-13 02:46:57 +04:00
|
|
|
switch(peer->peer_state) {
|
|
|
|
case MCA_OOB_TCP_CONNECTING:
|
2007-04-25 05:55:40 +04:00
|
|
|
mca_oob_tcp_peer_complete_connect(peer, sd);
|
2004-07-13 02:46:57 +04:00
|
|
|
break;
|
|
|
|
case MCA_OOB_TCP_CONNECTED:
|
|
|
|
{
|
2004-09-16 16:58:50 +04:00
|
|
|
while(peer->peer_send_msg != NULL) {
|
|
|
|
|
2004-08-03 01:24:00 +04:00
|
|
|
/* complete the current send */
|
2004-07-13 02:46:57 +04:00
|
|
|
mca_oob_tcp_msg_t* msg = peer->peer_send_msg;
|
2004-08-03 01:24:00 +04:00
|
|
|
if(mca_oob_tcp_msg_send_handler(msg, peer)) {
|
|
|
|
mca_oob_tcp_msg_complete(msg, &peer->peer_name);
|
|
|
|
} else {
|
2004-07-13 02:46:57 +04:00
|
|
|
break;
|
|
|
|
}
|
2004-08-03 01:24:00 +04:00
|
|
|
|
|
|
|
/* if current completed - progress any pending sends */
|
2004-07-13 02:46:57 +04:00
|
|
|
peer->peer_send_msg = (mca_oob_tcp_msg_t*)
|
2005-07-03 20:22:16 +04:00
|
|
|
opal_list_remove_first(&peer->peer_send_queue);
|
2004-09-16 16:58:50 +04:00
|
|
|
}
|
2004-07-15 17:51:40 +04:00
|
|
|
|
2004-07-13 02:46:57 +04:00
|
|
|
/* if nothing else to do unregister for send event notifications */
|
|
|
|
if(NULL == peer->peer_send_msg) {
|
2005-07-04 03:09:55 +04:00
|
|
|
opal_event_del(&peer->peer_send_event);
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
2005-07-04 03:31:27 +04:00
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_send_handler: invalid connection state (%d)",
|
2005-03-14 23:57:21 +03:00
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
2004-07-13 02:46:57 +04:00
|
|
|
peer->peer_state);
|
2005-07-04 03:09:55 +04:00
|
|
|
opal_event_del(&peer->peer_send_event);
|
2004-07-13 02:46:57 +04:00
|
|
|
break;
|
|
|
|
}
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_UNLOCK(&peer->peer_lock);
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Routine for debugging to print the connection state and socket options
|
|
|
|
*/
|
|
|
|
static void mca_oob_tcp_peer_dump(mca_oob_tcp_peer_t* peer, const char* msg)
|
|
|
|
{
|
|
|
|
char src[64];
|
|
|
|
char dst[64];
|
|
|
|
char buff[255];
|
|
|
|
int sndbuf,rcvbuf,nodelay,flags;
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
struct sockaddr_in6 inaddr;
|
|
|
|
opal_socklen_t addrlen = sizeof(struct sockaddr_in6);
|
|
|
|
#else
|
2004-07-13 02:46:57 +04:00
|
|
|
struct sockaddr_in inaddr;
|
2006-09-15 01:29:51 +04:00
|
|
|
opal_socklen_t addrlen = sizeof(struct sockaddr_in);
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
|
|
|
opal_socklen_t optlen;
|
2004-07-13 02:46:57 +04:00
|
|
|
|
|
|
|
getsockname(peer->peer_sd, (struct sockaddr*)&inaddr, &addrlen);
|
2007-04-25 05:55:40 +04:00
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
sprintf(src, "%s", opal_sockaddr2str(&inaddr));
|
|
|
|
getpeername(peer->peer_sd, (struct sockaddr*)&inaddr, &addrlen);
|
|
|
|
sprintf(dst, "%s", opal_sockaddr2str(&inaddr));
|
|
|
|
#else
|
2004-07-13 02:46:57 +04:00
|
|
|
sprintf(src, "%s", inet_ntoa(inaddr.sin_addr));
|
|
|
|
getpeername(peer->peer_sd, (struct sockaddr*)&inaddr, &addrlen);
|
|
|
|
sprintf(dst, "%s", inet_ntoa(inaddr.sin_addr));
|
2007-04-25 05:55:40 +04:00
|
|
|
#endif
|
2004-07-13 02:46:57 +04:00
|
|
|
|
|
|
|
if((flags = fcntl(peer->peer_sd, F_GETFL, 0)) < 0) {
|
2006-12-14 21:20:43 +03:00
|
|
|
opal_output(0, "mca_oob_tcp_peer_dump: fcntl(F_GETFL) failed: %s (%d)\n",
|
|
|
|
strerror(opal_socket_errno),
|
|
|
|
opal_socket_errno);
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(SO_SNDBUF)
|
|
|
|
optlen = sizeof(sndbuf);
|
|
|
|
if(getsockopt(peer->peer_sd, SOL_SOCKET, SO_SNDBUF, (char *)&sndbuf, &optlen) < 0) {
|
2006-12-14 21:20:43 +03:00
|
|
|
opal_output(0, "mca_oob_tcp_peer_dump: SO_SNDBUF option: %s (%d)\n",
|
|
|
|
strerror(opal_socket_errno),
|
|
|
|
opal_socket_errno);
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
sndbuf = -1;
|
|
|
|
#endif
|
|
|
|
#if defined(SO_RCVBUF)
|
|
|
|
optlen = sizeof(rcvbuf);
|
|
|
|
if(getsockopt(peer->peer_sd, SOL_SOCKET, SO_RCVBUF, (char *)&rcvbuf, &optlen) < 0) {
|
2006-12-14 21:20:43 +03:00
|
|
|
opal_output(0, "mca_oob_tcp_peer_dump: SO_RCVBUF option: %s (%d)\n",
|
|
|
|
strerror(opal_socket_errno),
|
|
|
|
opal_socket_errno);
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
rcvbuf = -1;
|
|
|
|
#endif
|
|
|
|
#if defined(TCP_NODELAY)
|
|
|
|
optlen = sizeof(nodelay);
|
2004-10-28 22:13:43 +04:00
|
|
|
if(getsockopt(peer->peer_sd, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, &optlen) < 0) {
|
2006-12-14 21:20:43 +03:00
|
|
|
opal_output(0, "mca_oob_tcp_peer_dump: TCP_NODELAY option: %s (%d)\n",
|
|
|
|
strerror(opal_socket_errno),
|
|
|
|
opal_socket_errno);
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
nodelay = 0;
|
|
|
|
#endif
|
2004-09-29 21:18:14 +04:00
|
|
|
|
2005-05-08 17:22:55 +04:00
|
|
|
sprintf(buff, "[%lu,%lu,%lu]-[%lu,%lu,%lu] %s: %s - %s nodelay %d sndbuf %d rcvbuf %d flags %08x\n",
|
2005-03-14 23:57:21 +03:00
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)),
|
2004-07-13 02:46:57 +04:00
|
|
|
msg, src, dst, nodelay, sndbuf, rcvbuf, flags);
|
2005-07-04 03:31:27 +04:00
|
|
|
opal_output(0, buff);
|
2004-07-13 02:46:57 +04:00
|
|
|
}
|
|
|
|
|
2004-08-03 01:24:00 +04:00
|
|
|
|
|
|
|
/*
|
Bring over the update to terminate orteds that are generated by a dynamic spawn such as comm_spawn. This introduces the concept of a job "family" - i.e., jobs that have a parent/child relationship. Comm_spawn'ed jobs have a parent (the one that spawned them). We track that relationship throughout the lineage - i.e., if a comm_spawned job in turn calls comm_spawn, then it has a parent (the one that spawned it) and a "root" job (the original job that started things).
Accordingly, there are new APIs to the name service to support the ability to get a job's parent, root, immediate children, and all its descendants. In addition, the terminate_job, terminate_orted, and signal_job APIs for the PLS have been modified to accept attributes that define the extent of their actions. For example, doing a "terminate_job" with an attribute of ORTE_NS_INCLUDE_DESCENDANTS will terminate the given jobid AND all jobs that descended from it.
I have tested this capability on a MacBook under rsh, Odin under SLURM, and LANL's Flash (bproc). It worked successfully on non-MPI jobs (both simple and including a spawn), and MPI jobs (again, both simple and with a spawn).
This commit was SVN r12597.
2006-11-14 22:34:59 +03:00
|
|
|
* Accept incoming connection - if not already connected. We compare the name of the
|
|
|
|
* peer to our own name using the ns.compare_fields function as we want this to be
|
|
|
|
* a LITERAL comparison - i.e., there is no occasion when the peer's name should
|
|
|
|
* be a wildcard value.
|
|
|
|
*
|
|
|
|
* To avoid competing reciprocal connection attempts, we only accept connections from
|
|
|
|
* processes whose names are "greater" than our own.
|
2004-08-03 01:24:00 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
bool mca_oob_tcp_peer_accept(mca_oob_tcp_peer_t* peer, int sd)
|
|
|
|
{
|
2005-03-14 23:57:21 +03:00
|
|
|
int cmpval;
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_LOCK(&peer->peer_lock);
|
Bring over the update to terminate orteds that are generated by a dynamic spawn such as comm_spawn. This introduces the concept of a job "family" - i.e., jobs that have a parent/child relationship. Comm_spawn'ed jobs have a parent (the one that spawned them). We track that relationship throughout the lineage - i.e., if a comm_spawned job in turn calls comm_spawn, then it has a parent (the one that spawned it) and a "root" job (the original job that started things).
Accordingly, there are new APIs to the name service to support the ability to get a job's parent, root, immediate children, and all its descendants. In addition, the terminate_job, terminate_orted, and signal_job APIs for the PLS have been modified to accept attributes that define the extent of their actions. For example, doing a "terminate_job" with an attribute of ORTE_NS_INCLUDE_DESCENDANTS will terminate the given jobid AND all jobs that descended from it.
I have tested this capability on a MacBook under rsh, Odin under SLURM, and LANL's Flash (bproc). It worked successfully on non-MPI jobs (both simple and including a spawn), and MPI jobs (again, both simple and with a spawn).
This commit was SVN r12597.
2006-11-14 22:34:59 +03:00
|
|
|
cmpval = orte_ns.compare_fields(ORTE_NS_CMP_ALL, &peer->peer_name, orte_process_info.my_name);
|
2004-08-03 01:24:00 +04:00
|
|
|
if ((peer->peer_state == MCA_OOB_TCP_CLOSED) ||
|
Not as bad as this all may look. Tim and I made a significant change to the way we handle the startup of the oob, the seed, etc. We have made it backwards-compatible so that mpirun2 and singleton operations remain working. We had to adjust the name server and gpr as well, plus the process_info structure.
This also includes a checkpoint update to openmpi.c and ompid.c. I have re-enabled the ompid compile.
This latter raises an important point. The trunk compiles the programs like ompid just fine under Linux. It also does just fine for OSX under the dynamic libraries. However, we are seeing errors when compiling under OSX for the static case - the linker seems to have trouble resolving some variable names, even though linker diagnostics show the variables as being defined. Thus, a warning to Mac users that you may have to locally turn things off if you are trying to do static compiles. We ask, however, that you don't commit those changes that turn things off for everyone else - instead, let's try to figure out why the static compile is having a problem, and let everyone else continue to work.
Thanks
Ralph
This commit was SVN r2534.
2004-09-08 07:59:06 +04:00
|
|
|
(peer->peer_state == MCA_OOB_TCP_RESOLVE) ||
|
2004-08-03 01:24:00 +04:00
|
|
|
(peer->peer_state != MCA_OOB_TCP_CONNECTED &&
|
Bring over the update to terminate orteds that are generated by a dynamic spawn such as comm_spawn. This introduces the concept of a job "family" - i.e., jobs that have a parent/child relationship. Comm_spawn'ed jobs have a parent (the one that spawned them). We track that relationship throughout the lineage - i.e., if a comm_spawned job in turn calls comm_spawn, then it has a parent (the one that spawned it) and a "root" job (the original job that started things).
Accordingly, there are new APIs to the name service to support the ability to get a job's parent, root, immediate children, and all its descendants. In addition, the terminate_job, terminate_orted, and signal_job APIs for the PLS have been modified to accept attributes that define the extent of their actions. For example, doing a "terminate_job" with an attribute of ORTE_NS_INCLUDE_DESCENDANTS will terminate the given jobid AND all jobs that descended from it.
I have tested this capability on a MacBook under rsh, Odin under SLURM, and LANL's Flash (bproc). It worked successfully on non-MPI jobs (both simple and including a spawn), and MPI jobs (again, both simple and with a spawn).
This commit was SVN r12597.
2006-11-14 22:34:59 +03:00
|
|
|
cmpval == ORTE_VALUE1_GREATER)) {
|
2004-08-31 06:57:39 +04:00
|
|
|
|
|
|
|
if(peer->peer_state != MCA_OOB_TCP_CLOSED) {
|
|
|
|
mca_oob_tcp_peer_close(peer);
|
|
|
|
}
|
2004-08-03 01:24:00 +04:00
|
|
|
peer->peer_sd = sd;
|
|
|
|
mca_oob_tcp_peer_event_init(peer);
|
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
if(mca_oob_tcp_peer_send_connect_ack(peer, sd) != ORTE_SUCCESS) {
|
2005-07-04 03:31:27 +04:00
|
|
|
opal_output(0, "[%lu,%lu,%lu]-[%lu,%lu,%lu] mca_oob_tcp_peer_accept: "
|
2004-09-29 21:18:14 +04:00
|
|
|
"mca_oob_tcp_peer_send_connect_ack failed\n",
|
2005-03-14 23:57:21 +03:00
|
|
|
ORTE_NAME_ARGS(orte_process_info.my_name),
|
|
|
|
ORTE_NAME_ARGS(&(peer->peer_name)));
|
2004-08-03 01:24:00 +04:00
|
|
|
mca_oob_tcp_peer_close(peer);
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_UNLOCK(&peer->peer_lock);
|
2004-08-03 01:24:00 +04:00
|
|
|
return false;
|
|
|
|
}
|
2004-08-31 06:57:39 +04:00
|
|
|
|
2007-04-25 05:55:40 +04:00
|
|
|
mca_oob_tcp_peer_connected(peer, sd);
|
|
|
|
if (sd == peer->peer_sd) {
|
|
|
|
opal_event_add(&peer->peer_recv_event, 0);
|
|
|
|
}
|
|
|
|
#if OPAL_WANT_IPV6
|
|
|
|
if (sd == peer->peer6_sd) {
|
|
|
|
opal_event_add(&peer->peer6_recv_event, 0);
|
|
|
|
}
|
|
|
|
#endif
|
2005-03-19 02:40:08 +03:00
|
|
|
if(mca_oob_tcp_component.tcp_debug > 0) {
|
2004-09-02 03:07:40 +04:00
|
|
|
mca_oob_tcp_peer_dump(peer, "accepted");
|
|
|
|
}
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_UNLOCK(&peer->peer_lock);
|
2004-08-03 01:24:00 +04:00
|
|
|
return true;
|
|
|
|
}
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_UNLOCK(&peer->peer_lock);
|
2004-08-03 01:24:00 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-08-16 23:39:54 +04:00
|
|
|
/*
|
|
|
|
* resolve process name to an actual internet address.
|
|
|
|
*/
|
|
|
|
|
2004-09-02 03:07:40 +04:00
|
|
|
void mca_oob_tcp_peer_resolved(mca_oob_tcp_peer_t* peer, mca_oob_tcp_addr_t* addr)
|
2004-08-16 23:39:54 +04:00
|
|
|
{
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_LOCK(&peer->peer_lock);
|
2004-09-02 03:07:40 +04:00
|
|
|
peer->peer_addr = addr;
|
Not as bad as this all may look. Tim and I made a significant change to the way we handle the startup of the oob, the seed, etc. We have made it backwards-compatible so that mpirun2 and singleton operations remain working. We had to adjust the name server and gpr as well, plus the process_info structure.
This also includes a checkpoint update to openmpi.c and ompid.c. I have re-enabled the ompid compile.
This latter raises an important point. The trunk compiles the programs like ompid just fine under Linux. It also does just fine for OSX under the dynamic libraries. However, we are seeing errors when compiling under OSX for the static case - the linker seems to have trouble resolving some variable names, even though linker diagnostics show the variables as being defined. Thus, a warning to Mac users that you may have to locally turn things off if you are trying to do static compiles. We ask, however, that you don't commit those changes that turn things off for everyone else - instead, let's try to figure out why the static compile is having a problem, and let everyone else continue to work.
Thanks
Ralph
This commit was SVN r2534.
2004-09-08 07:59:06 +04:00
|
|
|
if((peer->peer_state == MCA_OOB_TCP_RESOLVE) ||
|
2005-07-03 20:22:16 +04:00
|
|
|
(peer->peer_state == MCA_OOB_TCP_CLOSED && opal_list_get_size(&peer->peer_send_queue))) {
|
2004-09-02 03:07:40 +04:00
|
|
|
mca_oob_tcp_peer_start_connect(peer);
|
2004-08-16 23:39:54 +04:00
|
|
|
}
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_UNLOCK(&peer->peer_lock);
|
2004-08-16 23:39:54 +04:00
|
|
|
}
|
|
|
|
|
2004-08-28 05:15:19 +04:00
|
|
|
/*
|
|
|
|
* Callback on timeout - retry connection attempt.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void mca_oob_tcp_peer_timer_handler(int sd, short flags, void* user)
|
|
|
|
{
|
2004-09-02 03:07:40 +04:00
|
|
|
/* start the connection to the peer */
|
|
|
|
mca_oob_tcp_peer_t* peer = (mca_oob_tcp_peer_t*)user;
|
2006-09-20 18:29:37 +04:00
|
|
|
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_LOCK(&peer->peer_lock);
|
2007-04-25 05:55:40 +04:00
|
|
|
if(peer->peer_state == MCA_OOB_TCP_CLOSED) {
|
Not as bad as this all may look. Tim and I made a significant change to the way we handle the startup of the oob, the seed, etc. We have made it backwards-compatible so that mpirun2 and singleton operations remain working. We had to adjust the name server and gpr as well, plus the process_info structure.
This also includes a checkpoint update to openmpi.c and ompid.c. I have re-enabled the ompid compile.
This latter raises an important point. The trunk compiles the programs like ompid just fine under Linux. It also does just fine for OSX under the dynamic libraries. However, we are seeing errors when compiling under OSX for the static case - the linker seems to have trouble resolving some variable names, even though linker diagnostics show the variables as being defined. Thus, a warning to Mac users that you may have to locally turn things off if you are trying to do static compiles. We ask, however, that you don't commit those changes that turn things off for everyone else - instead, let's try to figure out why the static compile is having a problem, and let everyone else continue to work.
Thanks
Ralph
This commit was SVN r2534.
2004-09-08 07:59:06 +04:00
|
|
|
mca_oob_tcp_peer_start_connect(peer);
|
2007-04-25 05:55:40 +04:00
|
|
|
}
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_UNLOCK(&peer->peer_lock);
|
2004-08-28 05:15:19 +04:00
|
|
|
}
|
2004-08-19 23:34:37 +04:00
|
|
|
|
2004-09-16 18:12:22 +04:00
|
|
|
/*
|
|
|
|
* Remove any references to the indicated message.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void mca_oob_tcp_peer_dequeue_msg(mca_oob_tcp_peer_t* peer, mca_oob_tcp_msg_t* msg)
|
|
|
|
{
|
2005-07-03 20:22:16 +04:00
|
|
|
opal_list_item_t* item;
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_LOCK(&peer->peer_lock);
|
2004-09-16 18:12:22 +04:00
|
|
|
if (peer->peer_send_msg == msg)
|
|
|
|
peer->peer_send_msg = NULL;
|
|
|
|
if (peer->peer_recv_msg == msg)
|
|
|
|
peer->peer_recv_msg = NULL;
|
|
|
|
|
2005-07-03 20:22:16 +04:00
|
|
|
for( item = opal_list_get_first(&peer->peer_send_queue);
|
|
|
|
item != opal_list_get_end(&peer->peer_send_queue);
|
|
|
|
item = opal_list_get_next(item)) {
|
|
|
|
if(item == (opal_list_item_t*)msg) {
|
|
|
|
opal_list_remove_item(&peer->peer_send_queue, item);
|
2004-09-16 18:12:22 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2005-07-04 02:45:48 +04:00
|
|
|
OPAL_THREAD_UNLOCK(&peer->peer_lock);
|
2004-09-16 18:12:22 +04:00
|
|
|
}
|
|
|
|
|
2004-08-31 06:57:39 +04:00
|
|
|
|
2005-10-31 19:21:11 +03:00
|
|
|
/**
|
|
|
|
* Set socket buffering
|
|
|
|
*/
|
|
|
|
|
|
|
|
void mca_oob_tcp_set_socket_options(int sd)
|
|
|
|
{
|
|
|
|
int optval;
|
|
|
|
#if defined(TCP_NODELAY)
|
|
|
|
optval = 1;
|
|
|
|
if(setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (char *)&optval, sizeof(optval)) < 0) {
|
2007-04-25 05:55:40 +04:00
|
|
|
opal_backtrace_print(stderr);
|
2006-12-14 21:20:43 +03:00
|
|
|
opal_output(0, "[%s:%d] setsockopt(TCP_NODELAY) failed: %s (%d)",
|
|
|
|
__FILE__, __LINE__,
|
|
|
|
strerror(opal_socket_errno),
|
|
|
|
opal_socket_errno);
|
2005-10-31 19:21:11 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if defined(SO_SNDBUF)
|
|
|
|
if(mca_oob_tcp_component.tcp_sndbuf > 0 &&
|
|
|
|
setsockopt(sd, SOL_SOCKET, SO_SNDBUF, (char *)&mca_oob_tcp_component.tcp_sndbuf, sizeof(int)) < 0) {
|
2006-12-14 21:20:43 +03:00
|
|
|
opal_output(0, "[%s:%d] setsockopt(SO_SNDBUF) failed: %s (%d)",
|
|
|
|
__FILE__, __LINE__,
|
|
|
|
strerror(opal_socket_errno),
|
|
|
|
opal_socket_errno);
|
2005-10-31 19:21:11 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if defined(SO_RCVBUF)
|
|
|
|
if(mca_oob_tcp_component.tcp_rcvbuf > 0 &&
|
|
|
|
setsockopt(sd, SOL_SOCKET, SO_RCVBUF, (char *)&mca_oob_tcp_component.tcp_rcvbuf, sizeof(int)) < 0) {
|
2006-12-14 21:20:43 +03:00
|
|
|
opal_output(0, "[%s:%d] setsockopt(SO_RCVBUF) failed: %s (%d)",
|
|
|
|
__FILE__, __LINE__,
|
|
|
|
strerror(opal_socket_errno),
|
|
|
|
opal_socket_errno);
|
2005-10-31 19:21:11 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|