Actual source code: send.c

  1: #define PETSC_DLL
 2:  #include petsc.h
 3:  #include petscsys.h

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

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

 49:  #include src/sys/viewer/impls/socket/socket.h
 50: #include "petscfix.h"

 53: #if defined(PETSC_NEED_CLOSE_PROTO)
 55: #endif
 56: #if defined(PETSC_NEED_SOCKET_PROTO)
 58: #endif
 59: #if defined(PETSC_NEED_SLEEP_PROTO)
 61: #endif
 62: #if defined(PETSC_NEED_CONNECT_PROTO)
 64: #endif

 67: /*--------------------------------------------------------------*/
 70: static PetscErrorCode PetscViewerDestroy_Socket(PetscViewer viewer)
 71: {
 72:   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data;
 73:   PetscErrorCode     ierr;

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

 88: /*--------------------------------------------------------------*/
 91: PetscErrorCode  SOCKCall_Private(char *hostname,int portnum,int *t)
 92: {
 93:   struct sockaddr_in sa;
 94:   struct hostent     *hp;
 95:   int                s = 0;
 96:   PetscErrorCode     ierr;
 97:   PetscTruth         flg = PETSC_TRUE;

100:   if (!(hp=gethostbyname(hostname))) {
101:     perror("SEND: error gethostbyname: ");
102:     SETERRQ1(PETSC_ERR_SYS,"system error open connection to %s",hostname);
103:   }
104:   PetscMemzero(&sa,sizeof(sa));
105:   PetscMemcpy(&sa.sin_addr,hp->h_addr,hp->h_length);

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

159: /*@C
160:    PetscViewerSocketOpen - Opens a connection to a Matlab or other socket
161:         based server.

163:    Collective on MPI_Comm

165:    Input Parameters:
166: +  comm - the MPI communicator
167: .  machine - the machine the server is running on
168: -  port - the port to connect to, use PETSC_DEFAULT for the default

170:    Output Parameter:
171: .  lab - a context to use when communicating with the server

173:    Level: intermediate

175:    Notes:
176:    Most users should employ the following commands to access the 
177:    Matlab PetscViewers
178: $
179: $    PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
180: $    MatView(Mat matrix,PetscViewer viewer)
181: $
182: $                or
183: $
184: $    PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
185: $    VecView(Vec vector,PetscViewer viewer)

187:    Options Database Keys:
188:    For use with  PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
189:    PETSC_VIEWER_SOCKET_() or if 
190:     PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
191: $    -viewer_socket_machine <machine>
192: $    -viewer_socket_port <port>

194:    Environmental variables:
195: +   PETSC_VIEWER_SOCKET_PORT portnumber
196: -   PETSC_VIEWER_SOCKET_MACHINE machine name

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

201:    Notes: The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket
202:           use PetscViewerBinaryRead/Write/GetDescriptor().

204:    Concepts: Matlab^sending data
205:    Concepts: sockets^sending data

207: .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
208:           PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD, 
209:           PETSC_VIEWER_SOCKET_SELF, PetscViewerBinaryWrite(), PetscViewerBinaryRead(), PetscViewerBinaryWriteStringArray(),
210:           PetscBinaryViewerGetDescriptor()
211: @*/
212: PetscErrorCode  PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
213: {

217:   PetscViewerCreate(comm,lab);
218:   PetscViewerSetType(*lab,PETSC_VIEWER_SOCKET);
219:   PetscViewerSocketSetConnection(*lab,machine,port);
220:   return(0);
221: }

225: PetscErrorCode PetscViewerSetFromOptions_Socket(PetscViewer v)
226: {
228:   PetscInt       def = -1;
229:   char           sdef[256];
230:   PetscTruth     tflg;

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

246:     PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);
247:     PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);
248:     if (!tflg) {
249:       PetscGetHostName(sdef,256);
250:     }
251:   PetscOptionsTail();
252:   return(0);
253: }

258: PetscErrorCode  PetscViewerCreate_Socket(PetscViewer v)
259: {
260:   PetscViewer_Socket *vmatlab;
261:   PetscErrorCode     ierr;

264:   PetscNewLog(v,PetscViewer_Socket,&vmatlab);
265:   vmatlab->port          = 0;
266:   v->data                = (void*)vmatlab;
267:   v->ops->destroy        = PetscViewerDestroy_Socket;
268:   v->ops->flush          = 0;
269:   v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;

271:   /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */
272:   PetscObjectChangeTypeName((PetscObject)v,PETSC_VIEWER_BINARY);
273:   return(0);
274: }

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

283:   Collective on PetscViewer

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

290:     Level: advanced

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

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

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

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


339: /*@C
340:      PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator.

342:      Collective on MPI_Comm

344:      Input Parameter:
345: .    comm - the MPI communicator to share the socket PetscViewer

347:      Level: intermediate

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

355:    Environmental variables:
356: +   PETSC_VIEWER_SOCKET_PORT portnumber
357: -   PETSC_VIEWER_SOCKET_MACHINE machine name

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

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

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

369: .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
370:           PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(),
371:           PetscViewerBinaryWriteStringArray(), PetscBinaryViewerGetDescriptor()
372: @*/
373: PetscViewer  PETSC_VIEWER_SOCKET_(MPI_Comm comm)
374: {
376:   PetscTruth     flg;
377:   PetscViewer    viewer;

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