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_STROPTS_H)
 43: #include <stropts.h>
 44: #endif
 45: #if defined(PETSC_HAVE_IO_H)
 46: #include <io.h>
 47: #endif
 48: #if defined(PETSC_HAVE_WINSOCK2_H)
 49: #include <Winsock2.h>
 50: #endif

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

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

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

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

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

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

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

162: /*@C
163:    PetscViewerSocketOpen - Opens a connection to a Matlab or other socket
164:         based server.

166:    Collective on MPI_Comm

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

173:    Output Parameter:
174: .  lab - a context to use when communicating with the server

176:    Level: intermediate

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

190:    Options Database Keys:
191:    For use with the default Matlab PetscViewer, PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
192:    PETSC_VIEWER_SOCKET_() or if 
193:     PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
194: $    -viewer_socket_machine <machine>
195: $    -viewer_socket_port <port>

197:    Environmental variables:
198: +   PETSC_VIEWER_SOCKET_PORT portnumber
199: -   PETSC_VIEWER_SOCKET_MACHINE machine name

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

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
210: @*/
211: PetscErrorCode PETSC_DLLEXPORT PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
212: {

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

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

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

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

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

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

275: /*@C
276:       PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket 
277:              viewer is to use

279:   Collective on PetscViewer

281:   Input Parameters:
282: +   v - viewer to connect
283: .   machine - host to connect to
284: -   port - the port on the machine one is connecting to

286:     Level: advanced

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

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

317:   MPI_Comm_rank(v->comm,&rank);
318:   if (!rank) {
319:     PetscLogInfo((0,"PetscViewerSocketSetConnection:Connecting to socket process on port %D machine %s\n",port,mach));
320:     SOCKCall_Private(mach,(int)port,&vmatlab->port);
321:   }
322:   return(0);
323: }

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


335: /*@C
336:      PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors 
337:                      in a communicator.

339:      Collective on MPI_Comm

341:      Input Parameter:
342: .    comm - the MPI communicator to share the socket PetscViewer

344:      Level: intermediate

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

352:    Environmental variables:
353: +   PETSC_VIEWER_SOCKET_PORT portnumber
354: -   PETSC_VIEWER_SOCKET_MACHINE machine name

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

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

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

366: .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
367:           PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_()
368: @*/
369: PetscViewer PETSC_DLLEXPORT PETSC_VIEWER_SOCKET_(MPI_Comm comm)
370: {
372:   PetscTruth     flg;
373:   PetscViewer    viewer;

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