diff options
-rw-r--r-- | param.ccl | 4 | ||||
-rw-r--r-- | schedule.ccl | 17 | ||||
-rw-r--r-- | src/IsoSurfacer.c | 26 | ||||
-rw-r--r-- | src/IsoSurfacerGH.h | 10 | ||||
-rw-r--r-- | src/Sockets.c | 812 | ||||
-rw-r--r-- | src/Startup.c | 15 | ||||
-rw-r--r-- | src/make.code.defn | 7 |
7 files changed, 869 insertions, 22 deletions
@@ -47,6 +47,10 @@ STRING outdir "Output directory for isosurface data files" .* :: A regex which matches everything } "." +BOOLEAN nusurfacer "Enable the new isosurfacer routines to be used rather than the originals ?" +{ +} "yes" + ############################################################################# ### import IOUtil parameters ############################################################################# diff --git a/schedule.ccl b/schedule.ccl index 5e75cee..e7713ab 100644 --- a/schedule.ccl +++ b/schedule.ccl @@ -1,10 +1,13 @@ # Schedule definitions for thorn IsoSurfacer # $Header$ -# schedule IsoSurfacer_Startup at STARTUP before (Webserver_Startup) +# schedule IsoSurfacer_Startup at STARTUP -#if (*isosurfacer != '\0') { - schedule IsoSurfacer_Startup at STARTUP - { - LANG:C - } "Startup routine" -#} +schedule IsoSurfacer_Startup at STARTUP +{ + LANG:C +} "Startup routine" + +schedule IsoSurfacer_Worker at POSTSTEP +{ + LANG:C +} "Polling routine" diff --git a/src/IsoSurfacer.c b/src/IsoSurfacer.c index 8baee5e..6ad8190 100644 --- a/src/IsoSurfacer.c +++ b/src/IsoSurfacer.c @@ -532,13 +532,22 @@ void CollectData(cGH *GH, polypatch *perprocessor, polypatch *totals) { /***************************************************************************/ +int IsoWriteDataToClients(const char *metadata, + CCTK_INT8 size, + IsoType type, + CCTK_INT4 *data); + void WriteSock(cGH *GH, polypatch *totals, par_st *parms, const char *fullname, int isoindex, CCTK_REAL4 IsoValue) { -#if 0 /* Was: parms->timestep, which was callnumber from above. */ char tmpstring[128]; + CCTK_INT4 *polys; + CCTK_REAL4 *verts; + CCTK_INT4 tmppolys[3] = {0,0,0}; + CCTK_REAL4 tmpverts[3] = {0.0,0.0,0.0}; + sprintf(tmpstring," :%s[0]=%f,%u range=%f:%f", fullname,parms->isovalue, GH->cctk_iteration, @@ -546,13 +555,18 @@ void WriteSock(cGH *GH, polypatch *totals, par_st *parms, puts(tmpstring); /********Now write vertices**********/ *tmpstring='v'; - verts = totals->nverts > 0 ? totals->verts : tmpvert; - DS->sendData(tmpstring,3*totals->nverts,DataType::int2type(REMOTE_IO_FLOAT32),verts); + verts = totals->nverts > 0 ? totals->verts : tmpverts; + IsoWriteDataToClients(tmpstring, + 3*totals->nverts, + Int32, + (CCTK_INT4 *)verts); /********Now write polygons**********/ *tmpstring='c'; - polys = totals->npolys > 0 ? totals->polys : tmppoly; - DS->sendData(tmpstring,3*totals->npolys,DataType::int2type(REMOTE_IO_INT32),polys); -#endif + polys = totals->npolys > 0 ? totals->polys : tmppolys; + IsoWriteDataToClients(tmpstring, + 3*totals->npolys, + Float32, + (CCTK_INT4 *)polys); } /***************************************************************************/ diff --git a/src/IsoSurfacerGH.h b/src/IsoSurfacerGH.h index 63194a9..6612e6c 100644 --- a/src/IsoSurfacerGH.h +++ b/src/IsoSurfacerGH.h @@ -1,4 +1,4 @@ -// The extensions to the GH structure from IsoSurfacer. +/* The extensions to the GH structure from IsoSurfacer. */ #ifndef __IsoSurface_GH_h_ #define __IsoSurface_GH_h_ @@ -24,4 +24,10 @@ typedef struct isosurfacerGH typedef isosurfacerGH isoparms_st; -#endif // __IsoSurface_GH_h_ +typedef enum {Byte=0,Int8=0,Int16=1,Int32=2,Int64=3, + Float32=4,Float64=5, + uInt8=6,uChar=6,uInt16=7,uInt32=8,uInt64=9, + Char=10,Char8=10,String=10,Unicode=11, + Char16=11, Error=-1} IsoType; + +#endif /* __IsoSurface_GH_h_ */ diff --git a/src/Sockets.c b/src/Sockets.c new file mode 100644 index 0000000..88c67d7 --- /dev/null +++ b/src/Sockets.c @@ -0,0 +1,812 @@ + /*@@ + @file Sockets.c + @date Wed Sep 13 20:39:15 2000 + @author Tom Goodale + @desc + Routines which deal with sockets. + These should probably move into thorn Socket at some point if + they aren't already there. + @enddesc + @version $Header$ + @@*/ + +#include "cctk.h" + +#include <stdio.h> +#include <stdlib.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif /* HAVE_UNISTD_H */ +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif /* HAVE_SYS_TIME_H */ +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif /* HAVE_SYS_TYPES_H */ +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif /* HAVE_SYS_SOCKET_H */ +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif /* HAVE_NETINET_IN_H */ +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif /* HAVE_NETDB_H */ +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif /* ARPA_INET_H */ +#ifdef HAVE_WINSOCK2_H +#include <winsock2.h> +#endif /* HAVE_WINSOCK2_H */ +#include <errno.h> + +#include "IsoSurfacerInit.h" +#include "IsoSurfacerGH.h" + +static char *rcsid = "$Header$"; + +CCTK_FILEVERSION(DevThorns_isosurfacer_Socket_c) + +/******************************************************************** + ********************* Local Data Types *********************** + ********************************************************************/ + +#ifndef SOCKET +#define SOCKET int +#endif + +#ifdef SOCKET_ERROR +#define ERROR_CHECK(a) ((a) == SOCKET_ERROR) +#else +#define ERROR_CHECK(a) ((a) < 0) +#endif + +#ifdef HAVE_WINSOCK2_H +#define CLOSESOCKET(a) closesocket(a) +#else +#define CLOSESOCKET(a) close(a) +#endif + +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL 0 +#endif + +typedef enum {closed, open} isoSocketState; + +typedef struct ISOSocket +{ + struct ISOSocket *prev; + struct ISOSocket *next; + unsigned long filedes; + isoSocketState state; +} isoSocket; + +/******************************************************************** + ********************* Local Routine Prototypes ********************* + ********************************************************************/ + +int Iso_Write(isoSocket *connection, const char *buffer, size_t count); + +static SOCKET Iso_MakeSocket (unsigned long port, int *hunt); + +static isoSocket *SocketCreate(unsigned long int filedes, isoSocket **list); +static void SocketDestroy(isoSocket *this, isoSocket **list); +static void SocketClose(isoSocket *this); + +static int InitialiseTCP(void); + +static int Iso_ReadFromClient(cGH *cctkGH, isoSocket *this); + +/******************************************************************** + ********************* Other Routine Prototypes ********************* + ********************************************************************/ + +/******************************************************************** + ********************* Local Data ***************************** + ********************************************************************/ + +/* Active file descriptors */ +static fd_set active_fd_set; + +/* Main server socket */ +static SOCKET datasock; +static SOCKET controlsock; + +static SOCKET minsock; +static SOCKET maxsock; + +static isoSocket *controlsocklist = NULL; +static isoSocket *datasocklist = NULL; + +/******************************************************************** + ********************* External Routines ********************** + ********************************************************************/ + + + /*@@ + @routine Iso_SetupServer + @date Wed Sep 13 20:39:15 2000 + @author Tom Goodale + @desc + Creates a socket to listen on. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int Iso_SetupServer(int dataport, int controlport, int queue_size, int hunt) +{ + char hostname[1025]; + int realdport; + int realcport; + + /* Some systems need special logic for starting up TCP. */ + InitialiseTCP(); + + /* Create the data socket and set it up to accept connections. */ + datasock = Iso_MakeSocket (dataport, hunt ? &realdport : NULL); + + if (ERROR_CHECK(listen (datasock, queue_size))) + { + perror ("listen"); + exit (EXIT_FAILURE); + } + + /* Create the control socket and set it up to accept connections. */ + controlsock = Iso_MakeSocket (controlport, hunt ? &realcport : NULL); + + if (ERROR_CHECK(listen (controlsock, queue_size))) + { + perror ("listen"); + exit (EXIT_FAILURE); + } + + gethostname(hostname, 1024); + + printf("Isosurfacer listening for control connetcions on %s port %d/\n", hostname, hunt ? realcport : controlport); + printf("Isosurfacer listening for data connections on %s port %d/\n", hostname, hunt ? realdport : dataport); + + minsock = datasock > controlsock ? controlsock : datasock; + maxsock = datasock > controlsock ? datasock : controlsock; + + + /* Initialize the set of active sockets. */ + FD_ZERO (&active_fd_set); + FD_SET (controlsock, &active_fd_set); + FD_SET (datasock, &active_fd_set); + + return 0; +} + + /*@@ + @routine Iso_ShutdownServer + @date Wed Sep 13 20:39:15 2000 + @author Tom Goodale + @desc + Closes all sockets we are interested in. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int Iso_ShutdownServer(void) +{ + SOCKET i; + + /* Close all sockets in our active set */ + for(i = maxsock; i >= minsock; i--) + { + if(FD_ISSET(i, &active_fd_set)) + { + CLOSESOCKET(i); + } + } + + return 0; +} + + /*@@ + @routine Iso_Poll + @date Wed Sep 13 20:39:15 2000 + @author Tom Goodale + @desc + Main workhorse routine. + Looks for activity on any of the sockets which are open + and dispatches work. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int Iso_Poll(cGH *cctkGH, long sec, long usec) +{ +#ifdef HAVE_SOCKLEN_T + socklen_t size; +#else + int size; +#endif + + fd_set read_fd_set; + + struct sockaddr_in clientname; + struct timeval timeout; + struct timeval *real_timeout; + + isoSocket *this; + isoSocket *next; + + if(sec >=0) + { + timeout.tv_sec = sec; + timeout.tv_usec = usec; + + real_timeout = &timeout; + } + else + { + real_timeout = NULL; + } + + /* Check if any input is available on one or more active sockets. */ + read_fd_set = active_fd_set; + + if (ERROR_CHECK(select (FD_SETSIZE, &read_fd_set, NULL, NULL, real_timeout))) + { + perror ("select"); + CCTK_Abort(cctkGH, EXIT_FAILURE); + } + + /* Service all the sockets with input pending. */ + if (FD_ISSET (datasock, &read_fd_set)) + { + /* Connection request on data socket. */ + SOCKET new; + size = sizeof (clientname); + new = accept (datasock, + (struct sockaddr *) &clientname, + &size); + if (ERROR_CHECK(new)) + { + perror ("accept"); + CCTK_Abort(cctkGH, EXIT_FAILURE); + } + fprintf (stderr, + "Isosurfacer: data connect from host %s, port %hd.\n", + inet_ntoa (clientname.sin_addr), + ntohs (clientname.sin_port)); + + SocketCreate(new, &datasocklist); + } + + if (FD_ISSET (controlsock, &read_fd_set)) + { + /* Connection request on data socket. */ + SOCKET new; + size = sizeof (clientname); + new = accept (controlsock, + (struct sockaddr *) &clientname, + &size); + if (ERROR_CHECK(new)) + { + perror ("accept"); + CCTK_Abort(cctkGH, EXIT_FAILURE); + } + fprintf (stderr, + "Isosurfacer: control connect from host %s, port %hd.\n", + inet_ntoa (clientname.sin_addr), + ntohs (clientname.sin_port)); + + SocketCreate(new, &controlsocklist); + } + + for(this = controlsocklist; this; this = next) + { + next = this->next; + if(FD_ISSET (this->filedes, &read_fd_set)) + { + /* Data arriving on an already-connected socket. */ + if (Iso_ReadFromClient (cctkGH, this) < 0) + { + SocketDestroy(this, &controlsocklist); + } + } + } + + + return 0; +} + +int IsoWriteDataToClients(const char *metadata, + CCTK_INT8 size, + IsoType type, + CCTK_INT4 *data) +{ + int retval; + CCTK_INT8 i; + CCTK_INT4 datatype; + CCTK_INT8 datasize; + isoSocket *this; + isoSocket *next; + + CCTK_INT4 tmppolys[3] = {0,0,0}; + CCTK_REAL4 tmpverts[3] = {0.0,0.0,0.0}; + + /* Convert the data to network byte order */ + for(i = 0; i < size; i++) + { + data[i] = htons(data[i]); + } + + datatype = type; + + datatype = htons(datatype); + + datasize = htonl(datasize); + + /* Send data down all connected sockets. */ + for(this = datasocklist; this; this = next) + { + next = this->next; + + Iso_Write(this, (void *)&datasize, 8); + Iso_Write(this, (void *)&datatype, 4); + Iso_Write(this, metadata, 64); + retval = Iso_Write(this, (void *)data, size); + + if(retval < 0) + { + SocketDestroy(this, &datasocklist); + } + } + + /* Convert the data back */ + for(i = 0; i < size; i++) + { + data[i] = htons(data[i]); + } + + +} + + + /*@@ + @routine Iso_Write + @date Fri Sep 15 18:47:41 2000 + @author Tom Goodale + @desc + Writes part or all of an Iso data connection. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int Iso_Write(isoSocket *connection, const char *buffer, size_t count) +{ + int retval; + size_t bytes_sent; + size_t halfcount; + int done; + int tmp; + fd_set this_set; + + if(connection->state == open) + { + FD_ZERO (&this_set); + done = 0; + bytes_sent = 0; + while(!done) + { + /* Try and send the data. Make sure we don't get a SIGPIPE if the + * other end is closed. + */ + retval = send(connection->filedes, + buffer+bytes_sent, + count-bytes_sent, + MSG_NOSIGNAL); + + /* Check for errors */ + if(ERROR_CHECK(retval)) + { + switch(errno) + { +#ifdef EMSGSIZE + case EMSGSIZE : /* The socket requires that message be sent atomically, + * and the size of the message to be sent made this + * impossible. + */ + /* Split message in two and try again. */ + halfcount = count/2; + retval = Iso_Write(connection, buffer, halfcount); + if(retval > -1) + { + tmp = Iso_Write(connection, buffer+halfcount, count-halfcount); + if(tmp > -1) + { + retval += tmp; + } + else + { + retval = tmp; + } + } + break; +#endif + +#ifdef ENOBUFS + case ENOBUFS : + /* The output queue for a network interface was full. This generally indicates that the interface has + * stopped sending, but may be caused by transient congestion. (This cannot occur in Linux, packets are + * just silently dropped when a device queue overflows.) + */ + retval = 0; + break; +#endif + case EBADF : /* An invalid descriptor was specified. */ +#ifdef ENOTSOCK + case ENOTSOCK : /* The filedescriptor is not a socket. */ +#endif + case EPIPE : /* The local end has been shut down on a connection oriented socket. In this case the process will also + * receive a SIGPIPE unless MSG_NOSIGNAL is set. + */ + SocketClose(connection); + break; + + case EINTR : /* A signal occurred.*/ + + case ENOMEM : /* No memory available. */ + + case EINVAL : /* Invalid argument passed. */ + + case EFAULT : /* An invalid user space address was specified for a parameter. */ + break; + +#if 0 + case EAGAIN : + case EWOULDBLOCK : + /* The socket is marked non-blocking and the requested operation would block. */ +#endif + default : + fprintf(stderr, "Error: this should never happen - %s %d", __FILE__, __LINE__); + } + } + else + { + bytes_sent += retval; + } + + if(!(ERROR_CHECK(retval)) && bytes_sent < count) + { + /* Wait until can write */ + FD_SET (connection->filedes, &this_set); + if (ERROR_CHECK(select (FD_SETSIZE, NULL, &this_set, NULL, NULL))) + { + perror ("select"); + CCTK_Abort(NULL, EXIT_FAILURE); + } + } + else + { + done = 1; + } + }; + } + else + { + retval = -1; + } + +#ifdef Iso_DEBUG + if(retval != -1) + { + fprintf (stderr, "Wrote: `%s'\n", buffer); + } + else + { + fprintf(stderr, "Couldn't write to the socket 8-(\n"); + } +#endif + + return retval; +} + + /*@@ + @routine Iso_Read + @date Mon Sep 18 10:14:03 2000 + @author Tom Goodale + @desc + Reads part or all of an Iso request. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int Iso_Read(isoSocket *connection, char *buffer, size_t count) +{ + int retval; + + if(connection->state == open) + { + /* Currently don't do anything fancy. */ + retval = recv(connection->filedes, buffer, count,MSG_NOSIGNAL); + +#ifdef Iso_DEBUG + fprintf (stderr, "Read: `%s'\n", buffer); +#endif + } + else + { + retval = -1; + } + + return retval; +} + +/******************************************************************** + ********************* Local Routines ************************* + ********************************************************************/ + + /*@@ + @routine Iso_MakeSocket + @date Wed Sep 13 20:39:15 2000 + @author Tom Goodale + @desc + Creates a socket. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int Iso_MakeSocket (unsigned long port, int *hunt) +{ + int this_sock; + struct sockaddr_in name; + int opt; + int done; + int realport; + int error; + + /* Create the socket. */ + this_sock = socket (PF_INET, SOCK_STREAM, 0); + if (ERROR_CHECK(this_sock)) + { + perror ("socket"); + CCTK_Abort(NULL, EXIT_FAILURE); + } + + /* Try to reuse the port if possible */ +#ifdef SO_REUSEADDR + opt = 1; + setsockopt(this_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); +#endif + + done = 0; + realport = port; + + while(!done) + { + /* Give the socket a name. */ + name.sin_family = AF_INET; + name.sin_port = htons (realport); + name.sin_addr.s_addr = htonl (INADDR_ANY); + if (ERROR_CHECK(error = bind (this_sock, (struct sockaddr *) &name, sizeof (name)))) + { + if(hunt) + { + /* Hunt for a new port */ + fprintf(stderr, "Port %u taken, trying %u\n", realport, realport+1); + realport++; + } + else + { + done = 1; + } + } + else + { + done = 1; + } + } + + if(ERROR_CHECK(error)) + { + perror ("bind"); + CCTK_Abort(NULL,EXIT_FAILURE); + } + else if(hunt) + { + *hunt = realport; + } + + return this_sock; +} + + /*@@ + @routine SocketCreate + @date Thu Sep 21 15:03:32 2000 + @author Tom Goodale + @desc + Creates an isoSocket structure and links it to the list. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +static isoSocket *SocketCreate(unsigned long int filedes, isoSocket **list) +{ + isoSocket *this; + + this = (isoSocket *)malloc(sizeof (isoSocket)); + + if(this) + { + this->filedes = filedes; + this->state = open; + this->prev = NULL; + this->next = *list; + + if(*list) + { + (*list)->prev = this; + } + + *list = this; + + FD_SET (this->filedes, &active_fd_set); + } + + return this; +} + + /*@@ + @routine SocketDestroy + @date Thu Sep 21 15:04:03 2000 + @author Tom Goodale + @desc + Destroys an isoSocket structure and removes it from the list. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +static void SocketDestroy(isoSocket *this, isoSocket **list) +{ + if(this) + { + if(this->state == open) + { + SocketClose(this); + } + + if(this->next) + { + this->next->prev = this->prev; + } + + if(this->prev) + { + this->prev->next=this->next; + } + else + { + *list = this->next; + } + + free(this); + } +} + + /*@@ + @routine SocketClose + @date Thu Sep 21 15:04:27 2000 + @author Tom Goodale + @desc + Closes the socket associated with an isoSocket structure. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +static void SocketClose(isoSocket *this) +{ + if(this) + { + if(this->state == open) + { + CLOSESOCKET(this->filedes); + this->state=closed; + FD_CLR (this->filedes, &active_fd_set); + } + } +} + + /*@@ + @routine Iso_ReadFromClient + @date Wed Oct 4 11:27:32 2000 + @author Tom Goodale + @desc + Reads a client command. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +static int Iso_ReadFromClient(cGH *cctkGH, isoSocket *this) +{ + return -1; +} + +/****************************************************************************** + ****************************************************************************** + ******************************************************************************/ + +/* Special code for starting up the socket layer. */ + +#ifdef HAVE_WINSOCK2_H +#ifndef _M_IX86 +#define _M_IX86 400 +#endif + +#include <sys/types.h> +#include <windows.h> +#include <stdio.h> + +static int InitialiseTCP(void) +{ + WORD wVersionRequested; + WSADATA wsaData; + int errnumber; + + wVersionRequested = MAKEWORD( 2, 0 ); + + errnumber = WSAStartup( wVersionRequested, &wsaData ); + + if (errnumber) + { + fprintf(stderr, "Couldn't start Windows socket layer\n"); + } + else + { + printf("Windows socket layer initialized.\n"); + } + + return errnumber; +} + +#else + +static int InitialiseTCP(void) +{ + return 0; +} + +#endif /* defined HAVE_WINSOCK2_H */ diff --git a/src/Startup.c b/src/Startup.c index 9a93ad9..987b0e0 100644 --- a/src/Startup.c +++ b/src/Startup.c @@ -16,11 +16,18 @@ #include "cctk_IOMethods.h" #include "IsoSurfacerInit.h" -void IsoSurfacer_Startup() +#include "cctk_Arguments.h" +#include "cctk_Parameters.h" + +int Iso_SetupServer(int dataport, int clientport, int queue_size, int hunt); + +int IsoSurfacer_Startup(void) { int IOMethod; int IsoSurfacer_GHExtension; + Iso_SetupServer(7051, 7050, 5, 1); + IsoSurfacer_GHExtension = CCTK_RegisterGHExtension ("IsoSurfacer"); CCTK_RegisterGHExtensionSetupGH (IsoSurfacer_GHExtension,IsoSurfacer_SetupGH); CCTK_RegisterGHExtensionInitGH (IsoSurfacer_GHExtension, IsoSurfacer_InitGH); @@ -33,3 +40,9 @@ void IsoSurfacer_Startup() } +int Iso_Poll(cGH *cctkGH, long sec, long usec); + +void IsoSurfacer_Worker(CCTK_ARGUMENTS) +{ + Iso_Poll(cctkGH, 0, 0); +} diff --git a/src/make.code.defn b/src/make.code.defn index 4145cb4..1ccb5ec 100644 --- a/src/make.code.defn +++ b/src/make.code.defn @@ -1,13 +1,8 @@ # Main make.code.defn file for thorn IsoSurfacer # $Header$ --include $(CCTK_HOME)/arrangements/external/TCPXX/src/make.code.defn - # Source files in this directory SRCS = Startup.c IsoSurfacerInit.c IsoSurfacer.c \ - NuSurfacer.c - -INC_DIRS += $(CCTK_HOME)/arrangements/external/TCPXX/src/ \ - $(CCTK_HOME)/arrangements/external/RemoteIO/src + NuSurfacer.c Sockets.c |