Actual source code: send.c

  1: /* $Id: send.c,v 1.123 2001/04/10 19:34:04 bsmith Exp $ */

 3:  #include petsc.h
 4:  #include petscsys.h

  6: #if defined(PETSC_NEEDS_UTYPE_TYPEDEFS)
  7: /* Some systems have inconsistent include files that use but do not
  8:    ensure that the following definitions are made */
  9: typedef unsigned char   u_char;
 10: typedef unsigned short  u_short;
 11: typedef unsigned short  ushort;
 12: typedef unsigned int    u_int;
 13: typedef unsigned long   u_long;
 14: #endif

 16: #include <errno.h>
 17: #if defined(PETSC_HAVE_STDLIB_H)
 18: #include <stdlib.h>
 19: #endif
 20: #include <sys/types.h>
 21: #include <ctype.h>
 22: #if defined(PETSC_HAVE_MACHINE_ENDIAN_H)
 23: #include <machine/endian.h>
 24: #endif
 25: #if defined(PETSC_HAVE_UNISTD_H)
 26: #include <unistd.h>
 27: #endif
 28: #if !defined(PARCH_win32)
 29: #include <sys/socket.h>
 30: #include <sys/wait.h>
 31: #include <netinet/in.h>
 32: #include <netdb.h>
 33: #include <fcntl.h>
 34: #if defined(PETSC_HAVE_STROPTS_H)
 35: #include <stropts.h>
 36: #endif
 37: #if defined (PETSC_HAVE_IO_H)
 38: #include <io.h>
 39: #endif

 41:  #include src/sys/src/viewer/impls/socket/socket.h
 42: #include "petscfix.h"

 44: EXTERN_C_BEGIN
 45: #if defined(PETSC_NEED_CLOSE_PROTO)
 46: extern int close(int);
 47: #endif
 48: #if defined(PETSC_NEED_SOCKET_PROTO)
 49: extern int socket(int,int,int);
 50: #endif
 51: #if defined(PETSC_NEED_SLEEP_PROTO)
 52: extern int sleep(unsigned);
 53: #endif
 54: #if defined(PETSC_NEED_CONNECT_PROTO)
 55: extern int connect(int,struct sockaddr *,int);
 56: #endif
 57: EXTERN_C_END

 59: /*--------------------------------------------------------------*/
 60: static int PetscViewerDestroy_Socket(PetscViewer viewer)
 61: {
 62:   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data;
 63:   int                ierr;

 66:   if (vmatlab->port) {
 67:     close(vmatlab->port);
 68:     if (ierr) SETERRQ(PETSC_ERR_LIB,"System error closing socket");
 69:   }
 70:   PetscFree(vmatlab);
 71:   return(0);
 72: }

 74: /*--------------------------------------------------------------*/
 75: int SOCKCall_Private(char *hostname,int portnum,int *t)
 76: {
 77: #if !defined(PETSC_MISSING_SOCKETS)
 78:   struct sockaddr_in sa;
 79:   struct hostent     *hp;
 80:   int                s = 0,ierr;
 81:   PetscTruth         flg = PETSC_TRUE;
 82: #endif

 85: #if defined(PETSC_MISSING_SOCKETS)
 86:   SETERRQ(1,"This system does not support Unix tcp/ip");
 87: #else
 88:   if (!(hp=gethostbyname(hostname))) {
 89:     perror("SEND: error gethostbyname: ");
 90:     SETERRQ1(PETSC_ERR_LIB,"system error open connection to %s",hostname);
 91:   }
 92:   PetscMemzero(&sa,sizeof(sa));
 93:   PetscMemcpy(&sa.sin_addr,hp->h_addr,hp->h_length);

 95:   sa.sin_family = hp->h_addrtype;
 96:   sa.sin_port = htons((u_short) portnum);
 97:   while (flg) {
 98:     if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) {
 99:       perror("SEND: error socket");  SETERRQ(PETSC_ERR_LIB,"system error");
100:     }
101:     if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
102:        if (errno == EADDRINUSE) {
103:         (*PetscErrorPrintf)("SEND: address is in usen");
104:       }
105: #if !defined(PARCH_win32_gnu)
106:        else if (errno == EALREADY) {
107:         (*PetscErrorPrintf)("SEND: socket is non-blocking n");
108:       }
109:       else if (errno == EISCONN) {
110:         (*PetscErrorPrintf)("SEND: socket already connectedn");
111:         sleep((unsigned) 1);
112:       }
113: #endif
114:       else if (errno == ECONNREFUSED) {
115:         /* (*PetscErrorPrintf)("SEND: forcefully rejectedn"); */
116:         sleep((unsigned) 1);
117:       } else {
118:         perror(NULL); SETERRQ(PETSC_ERR_LIB,"system error");
119:       }
120:       flg = PETSC_TRUE; close(s);
121:     }
122:     else flg = PETSC_FALSE;
123:   }
124:   *t = s;
125: #endif
126:   return(0);
127: }

129: /*@C
130:    PetscViewerSocketOpen - Opens a connection to a Matlab or other socket
131:         based server.

133:    Collective on MPI_Comm

135:    Input Parameters:
136: +  comm - the MPI communicator
137: .  machine - the machine the server is running on
138: -  port - the port to connect to, use PETSC_DEFAULT for the default

140:    Output Parameter:
141: .  lab - a context to use when communicating with the server

143:    Level: intermediate

145:    Notes:
146:    Most users should employ the following commands to access the 
147:    Matlab PetscViewers
148: $
149: $    PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
150: $    MatView(Mat matrix,PetscViewer viewer)
151: $
152: $                or
153: $
154: $    PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
155: $    VecView(Vec vector,PetscViewer viewer)

157:    Options Database Keys:
158:    For use with the default Matlab PetscViewer, PetscViewer_SOCKET_WORLD or if 
159:     PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
160: $    -viewer_socket_machine <machine>
161: $    -viewer_socket_port <port>

163:    Environmental variables:
164: +   PETSC_VIEWER_SOCKET_PORT portnumber
165: -   PETSC_VIEWER_SOCKET_MACHINE machine name

167:      Currently the only socket client available is Matlab. See 
168:      src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.

170:    Concepts: Matlab^sending data
171:    Concepts: sockets^sending data

173: .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
174:           PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD, 
175:           PETSC_VIEWER_SOCKET_SELF
176: @*/
177: int PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
178: {

182:   PetscViewerCreate(comm,lab);
183:   PetscViewerSetType(*lab,PETSC_VIEWER_SOCKET);
184:   PetscViewerSocketSetConnection(*lab,machine,port);
185:   return(0);
186: }

188: int PetscViewerSetFromOptions_Socket(PetscViewer v)
189: {
190:   int           ierr,def = -1;
191:   char          sdef[256];
192:   PetscTruth    tflg;

195:   /*
196:        These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
197:     are listed here for the GUI to display
198:   */
199:   PetscOptionsHead("Socket PetscViewer Options");
200:     PetscOptionsGetenv(v->comm,"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);
201:     if (tflg) {
202:       PetscOptionsAtoi(sdef,&def);
203:     } else {
204:       def = DEFAULTPORT;
205:     }
206:     PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);

208:     PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);
209:     PetscOptionsGetenv(v->comm,"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);
210:     if (!tflg) {
211:       PetscGetHostName(sdef,256);
212:     }
213:   PetscOptionsTail();
214:   return(0);
215: }

217: EXTERN_C_BEGIN
218: int PetscViewerCreate_Socket(PetscViewer v)
219: {
220:   PetscViewer_Socket *vmatlab;
221:   int                ierr;

224:   ierr                   = PetscNew(PetscViewer_Socket,&vmatlab);
225:   vmatlab->port          = 0;
226:   v->data                = (void*)vmatlab;
227:   v->ops->destroy        = PetscViewerDestroy_Socket;
228:   v->ops->flush          = 0;
229:   v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;
230:   return(0);
231: }
232: EXTERN_C_END

234: int PetscViewerSocketSetConnection(PetscViewer v,const char machine[],int port)
235: {
236:   int                ierr,rank;
237:   char               mach[256];
238:   PetscTruth         tflg;
239:   PetscViewer_Socket *vmatlab = (PetscViewer_Socket *)v->data;

242:   if (port <= 0) {
243:     char portn[16];
244:     PetscOptionsGetenv(v->comm,"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);
245:     if (tflg) {
246:       PetscOptionsAtoi(portn,&port);
247:     } else {
248:       port = DEFAULTPORT;
249:     }
250:   }
251:   if (!machine) {
252:     PetscOptionsGetenv(v->comm,"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);
253:     if (!tflg) {
254:       PetscGetHostName(mach,256);
255:     }
256:   } else {
257:     PetscStrncpy(mach,machine,256);
258:   }

260:   MPI_Comm_rank(v->comm,&rank);
261:   if (!rank) {
262:     PetscLogInfo(0,"PetscViewerSocketSetConnection:Connecting to socket process on port %d machine %sn",port,mach);
263:     SOCKCall_Private(mach,port,&vmatlab->port);
264:   }
265:   return(0);
266: }

268: /* ---------------------------------------------------------------------*/
269: /*
270:     The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
271:   is attached to a communicator, in this case the attribute is a PetscViewer.
272: */
273: static int Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;

275: /*@C
276:      PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors 
277:                      in a communicator.

279:      Collective on MPI_Comm

281:      Input Parameter:
282: .    comm - the MPI communicator to share the socket PetscViewer

284:      Level: intermediate

286:    Options Database Keys:
287:    For use with the default Matlab PetscViewer, PETSC_VIEWER_SOCKET_WORLD or if 
288:     PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
289: $    -viewer_socket_machine <machine>
290: $    -viewer_socket_port <port>

292:    Environmental variables:
293: +   PETSC_VIEWER_SOCKET_PORT portnumber
294: -   PETSC_VIEWER_SOCKET_MACHINE machine name

296:      Notes:
297:      Unlike almost all other PETSc routines, PetscViewer_SOCKET_ does not return 
298:      an error code.  The socket PetscViewer is usually used in the form
299: $       XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm));

301:      Currently the only socket client available is Matlab. See 
302:      src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.

304:      Connects to a waiting socket and stays connected until PetscViewerDestroy() is called.

306: .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
307:           PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_()
308: @*/
309: PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm)
310: {
311:   int         ierr;
312:   PetscTruth  flg;
313:   PetscViewer viewer;

316:   if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) {
317:     MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0);
318:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
319:   }
320:   MPI_Attr_get(comm,Petsc_Viewer_Socket_keyval,(void **)&viewer,(int *)&flg);
321:   if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
322:   if (!flg) { /* PetscViewer not yet created */
323:     PetscViewerSocketOpen(comm,0,0,&viewer);
324:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
325:     PetscObjectRegisterDestroy((PetscObject)viewer);
326:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_STDOUT_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
327:     MPI_Attr_put(comm,Petsc_Viewer_Socket_keyval,(void*)viewer);
328:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
329:   }
330:   PetscFunctionReturn(viewer);
331: }

333: #else /* defined (PARCH_win32) */
334: 
335:  #include petscviewer.h
336: int PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
337: {
339:   return(0);
340: }
341: PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm)
342: {
344:   return(0);
345: }
346: EXTERN_C_BEGIN
347: int PetscViewerCreate_Socket(PetscViewer v)
348: {
350:   return(0);
351: }
352: EXTERN_C_END
353: #endif