Actual source code: send.c

  1: #include "petsc.h"
 2:  #include petscsys.h

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

 14: #include <errno.h>
 15: #if defined(PETSC_HAVE_STDLIB_H)
 16: #include <stdlib.h>
 17: #endif
 18: #include <sys/types.h>
 19: #include <ctype.h>
 20: #if defined(PETSC_HAVE_MACHINE_ENDIAN_H)
 21: #include <machine/endian.h>
 22: #endif
 23: #if defined(PETSC_HAVE_UNISTD_H)
 24: #include <unistd.h>
 25: #endif
 26: #if defined(PETSC_HAVE_SYS_SOCKET_H)
 27: #include <sys/socket.h>
 28: #endif
 29: #if defined(PETSC_HAVE_SYS_WAIT_H)
 30: #include <sys/wait.h>
 31: #endif
 32: #if defined(PETSC_HAVE_NETINET_IN_H)
 33: #include <netinet/in.h>
 34: #endif
 35: #if defined(PETSC_HAVE_NETDB_H)
 36: #include <netdb.h>
 37: #endif
 38: #if defined(PETSC_HAVE_FCNTL_H)
 39: #include <fcntl.h>
 40: #endif
 41: #if defined(PETSC_HAVE_STROPTS_H)
 42: #include <stropts.h>
 43: #endif
 44: #if defined(PETSC_HAVE_IO_H)
 45: #include <io.h>
 46: #endif
 47: #if defined(PETSC_HAVE_WINSOCK2_H)
 48: #include <Winsock2.h>
 49: #endif

 51:  #include src/sys/src/viewer/impls/socket/socket.h
 52: #include "petscfix.h"

 55: #if defined(PETSC_NEED_CLOSE_PROTO)
 57: #endif
 58: #if defined(PETSC_NEED_SOCKET_PROTO)
 60: #endif
 61: #if defined(PETSC_NEED_SLEEP_PROTO)
 63: #endif
 64: #if defined(PETSC_NEED_CONNECT_PROTO)
 66: #endif

 69: /*--------------------------------------------------------------*/
 72: static PetscErrorCode PetscViewerDestroy_Socket(PetscViewer viewer)
 73: {
 74:   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data;
 75:   PetscErrorCode     ierr;

 78:   if (vmatlab->port) {
 79: #if defined(PETSC_HAVE_CLOSESOCKET)
 80:     closesocket(vmatlab->port);
 81: #else
 82:     close(vmatlab->port);
 83: #endif
 84:     if (ierr) SETERRQ(PETSC_ERR_LIB,"System error closing socket");
 85:   }
 86:   PetscFree(vmatlab);
 87:   return(0);
 88: }

 90: /*--------------------------------------------------------------*/
 93: PetscErrorCode SOCKCall_Private(char *hostname,int portnum,int *t)
 94: {
 95: #if defined(PETSC_HAVE_SOCKET)
 96:   struct sockaddr_in sa;
 97:   struct hostent     *hp;
 98:   int                s = 0;
 99:   PetscErrorCode     ierr;
100:   PetscTruth         flg = PETSC_TRUE;
101: #endif

104: #if !defined(PETSC_HAVE_SOCKET)
105:   SETERRQ(PETSC_ERR_SUP_SYS,"This system does not support Unix tcp/ip");
106: #else
107:   if (!(hp=gethostbyname(hostname))) {
108:     perror("SEND: error gethostbyname: ");
109:     SETERRQ1(PETSC_ERR_LIB,"system error open connection to %s",hostname);
110:   }
111:   PetscMemzero(&sa,sizeof(sa));
112:   PetscMemcpy(&sa.sin_addr,hp->h_addr,hp->h_length);

114:   sa.sin_family = hp->h_addrtype;
115:   sa.sin_port = htons((u_short) portnum);
116:   while (flg) {
117:     if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) {
118:       perror("SEND: error socket");  SETERRQ(PETSC_ERR_LIB,"system error");
119:     }
120:     if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
121: #if defined(PETSC_HAVE_WSAGETLASTERROR)
122:       WSAGetLastError();
123:       if (ierr == WSAEADDRINUSE) {
124:         (*PetscErrorPrintf)("SEND: address is in use\n");
125:       } else if (ierr == WSAEALREADY) {
126:         (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
127:       } else if (ierr == WSAEISCONN) {
128:         (*PetscErrorPrintf)("SEND: socket already connected\n");
129:         Sleep((unsigned) 1);
130:       } else if (ierr == WSAECONNREFUSED) {
131:         /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */
132:         Sleep((unsigned) 1);
133:       } else {
134:         perror(NULL); SETERRQ(PETSC_ERR_LIB,"system error");
135:       }
136: #else
137:       if (errno == EADDRINUSE) {
138:         (*PetscErrorPrintf)("SEND: address is in use\n");
139:       } else if (errno == EALREADY) {
140:         (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
141:       } else if (errno == EISCONN) {
142:         (*PetscErrorPrintf)("SEND: socket already connected\n");
143:         sleep((unsigned) 1);
144:       } else if (errno == ECONNREFUSED) {
145:         /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */
146:         sleep((unsigned) 1);
147:       } else {
148:         perror(NULL); SETERRQ(PETSC_ERR_LIB,"system error");
149:       }
150: #endif
151:       flg = PETSC_TRUE;
152: #if defined(PETSC_HAVE_CLOSESOCKET)
153:       closesocket(s);
154: #else
155:       close(s);
156: #endif
157:     }
158:     else flg = PETSC_FALSE;
159:   }
160:   *t = s;
161: #endif
162:   return(0);
163: }

165: #if defined(PETSC_HAVE_SOCKET)
168: /*@C
169:    PetscViewerSocketOpen - Opens a connection to a Matlab or other socket
170:         based server.

172:    Collective on MPI_Comm

174:    Input Parameters:
175: +  comm - the MPI communicator
176: .  machine - the machine the server is running on
177: -  port - the port to connect to, use PETSC_DEFAULT for the default

179:    Output Parameter:
180: .  lab - a context to use when communicating with the server

182:    Level: intermediate

184:    Notes:
185:    Most users should employ the following commands to access the 
186:    Matlab PetscViewers
187: $
188: $    PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
189: $    MatView(Mat matrix,PetscViewer viewer)
190: $
191: $                or
192: $
193: $    PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
194: $    VecView(Vec vector,PetscViewer viewer)

196:    Options Database Keys:
197:    For use with the default Matlab PetscViewer, PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
198:    PETSC_VIEWER_SOCKET_() or if 
199:     PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
200: $    -viewer_socket_machine <machine>
201: $    -viewer_socket_port <port>

203:    Environmental variables:
204: +   PETSC_VIEWER_SOCKET_PORT portnumber
205: -   PETSC_VIEWER_SOCKET_MACHINE machine name

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

210:    Concepts: Matlab^sending data
211:    Concepts: sockets^sending data

213: .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
214:           PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD, 
215:           PETSC_VIEWER_SOCKET_SELF
216: @*/
217: PetscErrorCode PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
218: {

222:   PetscViewerCreate(comm,lab);
223:   PetscViewerSetType(*lab,PETSC_VIEWER_SOCKET);
224:   PetscViewerSocketSetConnection(*lab,machine,port);
225:   return(0);
226: }

230: PetscErrorCode PetscViewerSetFromOptions_Socket(PetscViewer v)
231: {
233:   PetscInt       def = -1;
234:   char           sdef[256];
235:   PetscTruth     tflg;

238:   /*
239:        These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
240:     are listed here for the GUI to display
241:   */
242:   PetscOptionsHead("Socket PetscViewer Options");
243:     PetscOptionsGetenv(v->comm,"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);
244:     if (tflg) {
245:       PetscOptionsAtoi(sdef,&def);
246:     } else {
247:       def = DEFAULTPORT;
248:     }
249:     PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);

251:     PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);
252:     PetscOptionsGetenv(v->comm,"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);
253:     if (!tflg) {
254:       PetscGetHostName(sdef,256);
255:     }
256:   PetscOptionsTail();
257:   return(0);
258: }

263: PetscErrorCode PetscViewerCreate_Socket(PetscViewer v)
264: {
265:   PetscViewer_Socket *vmatlab;
266:   PetscErrorCode     ierr;

269:   PetscNew(PetscViewer_Socket,&vmatlab);
270:   vmatlab->port          = 0;
271:   v->data                = (void*)vmatlab;
272:   v->ops->destroy        = PetscViewerDestroy_Socket;
273:   v->ops->flush          = 0;
274:   v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;
275:   return(0);
276: }

281: /*@C
282:       PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket 
283:              viewer is to use

285:   Collective on PetscViewer

287:   Input Parameters:
288: +   v - viewer to connect
289: .   machine - host to connect to
290: -   port - the port on the machine one is connecting to

292:     Level: advanced

294: .seealso: PetscViewerSocketOpen()
295: @*/
296: PetscErrorCode PetscViewerSocketSetConnection(PetscViewer v,const char machine[],PetscInt port)
297: {
298:   PetscErrorCode     ierr;
299:   PetscMPIInt        rank;
300:   char               mach[256];
301:   PetscTruth         tflg;
302:   PetscViewer_Socket *vmatlab = (PetscViewer_Socket *)v->data;

305:   if (port <= 0) {
306:     char portn[16];
307:     PetscOptionsGetenv(v->comm,"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);
308:     if (tflg) {
309:       PetscOptionsAtoi(portn,&port);
310:     } else {
311:       port = DEFAULTPORT;
312:     }
313:   }
314:   if (!machine) {
315:     PetscOptionsGetenv(v->comm,"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);
316:     if (!tflg) {
317:       PetscGetHostName(mach,256);
318:     }
319:   } else {
320:     PetscStrncpy(mach,machine,256);
321:   }

323:   MPI_Comm_rank(v->comm,&rank);
324:   if (!rank) {
325:     PetscLogInfo(0,"PetscViewerSocketSetConnection:Connecting to socket process on port %D machine %s\n",port,mach);
326:     SOCKCall_Private(mach,(int)port,&vmatlab->port);
327:   }
328:   return(0);
329: }

331: /* ---------------------------------------------------------------------*/
332: /*
333:     The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
334:   is attached to a communicator, in this case the attribute is a PetscViewer.
335: */
336: static PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;


341: /*@C
342:      PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors 
343:                      in a communicator.

345:      Collective on MPI_Comm

347:      Input Parameter:
348: .    comm - the MPI communicator to share the socket PetscViewer

350:      Level: intermediate

352:    Options Database Keys:
353:    For use with the default Matlab PetscViewer, PETSC_VIEWER_SOCKET_WORLD or if 
354:     PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
355: $    -viewer_socket_machine <machine>
356: $    -viewer_socket_port <port>

358:    Environmental variables:
359: +   PETSC_VIEWER_SOCKET_PORT portnumber
360: -   PETSC_VIEWER_SOCKET_MACHINE machine name

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

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

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

372: .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
373:           PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_()
374: @*/
375: PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm)
376: {
378:   PetscTruth     flg;
379:   PetscViewer    viewer;

382:   if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) {
383:     MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0);
384:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
385:   }
386:   MPI_Attr_get(comm,Petsc_Viewer_Socket_keyval,(void **)&viewer,(int*)&flg);
387:   if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
388:   if (!flg) { /* PetscViewer not yet created */
389:     PetscViewerSocketOpen(comm,0,0,&viewer);
390:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
391:     PetscObjectRegisterDestroy((PetscObject)viewer);
392:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
393:     MPI_Attr_put(comm,Petsc_Viewer_Socket_keyval,(void*)viewer);
394:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
395:   }
396:   PetscFunctionReturn(viewer);
397: }

399: #else /* !defined (PETSC_HAVE_SOCKET) */ 
400: 
403: PetscErrorCode PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
404: {
406:   return(0);
407: }
410: PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm)
411: {
413:   return(0);
414: }
418: PetscErrorCode PetscViewerCreate_Socket(PetscViewer v)
419: {
421:   return(0);
422: }
424: #endif