1
1
David Daniel 242f062386 Since I'm vanishing for a few weeks, a smattering of code from FTMPI
for possible consideration...

This commit was SVN r2245.
2004-08-20 01:01:09 +00:00

259 строки
6.6 KiB
C

/*
HARNESS G_HCORE
Innovative Computer Laboratory,
University of Tennessee,
Knoxville, TN, USA.
harness@cs.utk.edu
--------------------------------------------------------------------------
Authors:
Graham E Fagg <fagg@cs.utk.edu>
--------------------------------------------------------------------------
NOTICE
Permission to use, copy, modify, and distribute this software and
its documentation for any purpose and without fee is hereby granted
provided that the above copyright notice appear in all copies and
that both the copyright notice and this permission notice appear in
supporting documentation.
Neither the University of Tennessee nor the Authors make any
representations about the suitability of this software for any
purpose. This software is provided ``as is'' without express or
implied warranty.
HARNESS, HARNESS G_HCORE and FT_MPI was funded in part by the
U.S. Department of Energy.
*/
#include "msgbuf.h"
#include "msg.h"
#ifdef WIN32
#include "wincomm.h"
#else
#include "snipe_lite.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
/* Note this is a simple (bad) description of a basic header */
/*
0-3 PKMESSAGEVER used to make sure its a packed message.. so if its not, then drop it.... if we can.
4-7 PACKEDMESSAGELEN length of packed data in octets (can be zero but not negative)
8-11 SENDERS ID arbitary id that they specify
12-15 NUMBER OF TAGS if no tags then set to zero
16-((4*ntag)-1) individual tags ...
16+(4*ntag)- Start of packed data.
*/
/* Note to avoid using writeV etc we get a message buffer of our own JUST for packing stuff in and out of */
/* we don't use the msgbuf routines as that effects cache coherency */
char hdrbuf [4096];
/* this routine sends a message down a socket as a complete message */
/* this includes a simple header (sender, tag, length) */
/* if the free flag is set then the message buffer is freed */
/* if free is set then even if its not send it is still freed always */
/* return value is either the total length sent or an error */
/* if the complete amount is not sent then the buffer is not freed */
int send_pkmesg (int send_s,int myid,int ntag,int * tagp,int buf_id,int free_buf)
/* int send_s; socket to send_s */
/* int myid; ID I place in message header */
/* int ntag; Number of Tags in header */
/* int *tagp; pointer to Tags to put in header */
/* int buf_id; message buffer I am sending or if you want to send an EMPTY message send EMPTYMSGBUF */
/* int free_buf; non zero if you want to free the buffer up after a good send */
{
int len = 0;
char * buf_ptr;
int ret = -1;
int *data;
int valid;
int i;
if (buf_id != EMPTYMSGBUF) valid = check_buf (buf_id);
else valid = 1;
if (!valid) return (BADBUFFER);
if (buf_id != EMPTYMSGBUF)
get_msg_buf_info(buf_id,&buf_ptr,&len); /* get buffer info */
else {
buf_ptr = NULL; /* if empty message */
len = 0;
}
data = (int*) hdrbuf;
*data++ = htonl (PKMESSAGEVER);
*data++ = htonl (len);
*data++ = htonl (myid);
*data++ = htonl (ntag);
for (i=0;i<ntag;i++) { /* pack the tags */
*data++ = htonl (tagp[i]);
}
#ifdef VERBOSE
PRINT("TRYING TO SEND %d %d - size %d of buf %d\n",myid,ntag,len, buf_id);
#endif
while(ret < 1){
ret = writeconn(send_s,(char*) hdrbuf,sizeof(int)*(4+ntag));
if(ret <= 0){
if ((buf_id != EMPTYMSGBUF)&&(free_buf)) free_msg_buf(buf_id);
return(ret);
}
if(len > 0){
ret = writeconn(send_s,buf_ptr,len);
if(ret <= 0){
if ((buf_id != EMPTYMSGBUF)&&(free_buf)) free_msg_buf(buf_id);
return(ret);
}
else
if ((buf_id != EMPTYMSGBUF)&&(free_buf)) free_msg_buf(buf_id);
}
}
return(ret);
}
/* recv a packed message and return the buffer of the message / size etc */
/* This route will allocate a buffer if it is needed (i.e. if it has a */
/* payload). */
/* If there isn't enought space for all the tags it drops tags */
/* ntags can be NULL or 0 */
/* if there is a protocol error i.e. protocol versions don't match it bombs */
int recv_pkmesg (int recv_s,int * from,int * ntag,int * tagp,int * buf_id)
{
int len;
char * buf_ptr = NULL;
int *hdata;
int *hdata2;
int size;
int ret;
int client;
int i, j;
int tmp;
int rtags; /* how many tags to receive even if it drops some */
int tbid; /* temp buf id */
#ifdef VERBOSE
PRINT("Atempting to receive from %d via socket %d\n",recv_s, from);
#endif
/* download the data into the header buffer */
hdata = (int*) hdrbuf;
hdata2 = (int*) hdrbuf;
ret = readconn(recv_s,(char*)hdata,sizeof(int)*4);
if(!ret){
return(ret);
}
tmp = ntohl(hdata[0]);
if (tmp != PKMESSAGEVER) { /* Header check */
#ifdef VERBOSE
printf("Recv_pkmesg has received a message with an incorrect hdr [0x%x]\n", hdata[0]);
#endif
return (MSG_BAD_HEADER);
}
size = ntohl(hdata[1]);
client = ntohl(hdata[2]);
rtags = ntohl(hdata[3]);
#ifdef VERBOSE
printf("header 0x%x size %d from %d ntags %d\n",
tmp, size, client, rtags);
#endif
/* now we have a copy of the header we can overwrite the headerbuffer */
/* download the message tags into the header buffer */
if (rtags>0) {
hdata2 = (int*) hdrbuf;
ret = readconn(recv_s,(char*)hdata2,sizeof(int)*rtags);
if(!ret){
return(ret);
}
}
/* ok copy over the ones we have been given space for */
/* check to see if we are even excepting tags first ! */
if (ntag) {
j = *ntag;
if (j>rtags) j=rtags;
for(i=0;i<j;i++) {
*tagp = ntohl(*hdata2);
tagp++;
hdata2++;
}
/* NOTE we only do the conversion on the ones we keep. Saves a few usecs? */
/* return the number of tags copied down */
*ntag = j;
}
else
j = 0; /* no tags copied */
/* copy across the return info */
/* senders id */
if (from) *from = client;
/* if no data (payload) to copy in, return outa here */
if(size == 0){
if (buf_id) *buf_id = EMPTYMSGBUF;
return(0);
}
/* get a buffer for the incoming data */
/* the buffer must be resizable */
/* i.e. we need a buffer, resize one if needed */
/* Also we reset the unpack len (toend) value automatically on it */
tbid = get_msg_buf_of_size(size, 1, 1);
get_msg_buf_info(tbid, &buf_ptr, &len); /* get the buffers ptr */
ret = readconn(recv_s, buf_ptr, size); /* read socket into buffer */
/* now we need to return the buffer id */
/* if its been given a NULL pointer we blow it away */
if (!buf_id) { /* a null return address! */
#ifdef VERBOSE
printf("Recv_pkmesg has a valid buffer but a NULL return address!\n");
#endif
free_msg_buf (tbid); /* blow it away */
}
else
*buf_id = tbid; /* return it */
return(ret); /* return read data length */
}