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: #undef __FUNCT__  
 62: static int PetscViewerDestroy_Socket(PetscViewer viewer)
 63: {
 64:   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data;
 65:   int                ierr;

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

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

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

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

133: #undef __FUNCT__  
135: /*@C
136:    PetscViewerSocketOpen - Opens a connection to a Matlab or other socket
137:         based server.

139:    Collective on MPI_Comm

141:    Input Parameters:
142: +  comm - the MPI communicator
143: .  machine - the machine the server is running on
144: -  port - the port to connect to, use PETSC_DEFAULT for the default

146:    Output Parameter:
147: .  lab - a context to use when communicating with the server

149:    Level: intermediate

151:    Notes:
152:    Most users should employ the following commands to access the 
153:    Matlab PetscViewers
154: $
155: $    PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
156: $    MatView(Mat matrix,PetscViewer viewer)
157: $
158: $                or
159: $
160: $    PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
161: $    VecView(Vec vector,PetscViewer viewer)

163:    Options Database Keys:
164:    For use with the default Matlab PetscViewer, PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
165:    PETSC_VIEWER_SOCKET_() or if 
166:     PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
167: $    -viewer_socket_machine <machine>
168: $    -viewer_socket_port <port>

170:    Environmental variables:
171: +   PETSC_VIEWER_SOCKET_PORT portnumber
172: -   PETSC_VIEWER_SOCKET_MACHINE machine name

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

177:    Concepts: Matlab^sending data
178:    Concepts: sockets^sending data

180: .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
181:           PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD, 
182:           PETSC_VIEWER_SOCKET_SELF
183: @*/
184: int PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
185: {

189:   PetscViewerCreate(comm,lab);
190:   PetscViewerSetType(*lab,PETSC_VIEWER_SOCKET);
191:   PetscViewerSocketSetConnection(*lab,machine,port);
192:   return(0);
193: }

195: #undef __FUNCT__  
197: int PetscViewerSetFromOptions_Socket(PetscViewer v)
198: {
199:   int           ierr,def = -1;
200:   char          sdef[256];
201:   PetscTruth    tflg;

204:   /*
205:        These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
206:     are listed here for the GUI to display
207:   */
208:   PetscOptionsHead("Socket PetscViewer Options");
209:     PetscOptionsGetenv(v->comm,"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);
210:     if (tflg) {
211:       PetscOptionsAtoi(sdef,&def);
212:     } else {
213:       def = DEFAULTPORT;
214:     }
215:     PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);

217:     PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);
218:     PetscOptionsGetenv(v->comm,"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);
219:     if (!tflg) {
220:       PetscGetHostName(sdef,256);
221:     }
222:   PetscOptionsTail();
223:   return(0);
224: }

226: EXTERN_C_BEGIN
227: #undef __FUNCT__  
229: int PetscViewerCreate_Socket(PetscViewer v)
230: {
231:   PetscViewer_Socket *vmatlab;
232:   int                ierr;

235:   ierr                   = PetscNew(PetscViewer_Socket,&vmatlab);
236:   vmatlab->port          = 0;
237:   v->data                = (void*)vmatlab;
238:   v->ops->destroy        = PetscViewerDestroy_Socket;
239:   v->ops->flush          = 0;
240:   v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;
241:   return(0);
242: }
243: EXTERN_C_END

245: #undef __FUNCT__  
247: /*@C
248:       PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket 
249:              viewer is to use

251:   Collective on PetscViewer

253:   Input Parameters:
254: +   v - viewer to connect
255: .   machine - host to connect to
256: -   port - the port on the machine one is connecting to

258:     Level: advanced

260: .seealso: PetscViewerSocketOpen()
261: @*/
262: int PetscViewerSocketSetConnection(PetscViewer v,const char machine[],int port)
263: {
264:   int                ierr,rank;
265:   char               mach[256];
266:   PetscTruth         tflg;
267:   PetscViewer_Socket *vmatlab = (PetscViewer_Socket *)v->data;

270:   if (port <= 0) {
271:     char portn[16];
272:     PetscOptionsGetenv(v->comm,"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);
273:     if (tflg) {
274:       PetscOptionsAtoi(portn,&port);
275:     } else {
276:       port = DEFAULTPORT;
277:     }
278:   }
279:   if (!machine) {
280:     PetscOptionsGetenv(v->comm,"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);
281:     if (!tflg) {
282:       PetscGetHostName(mach,256);
283:     }
284:   } else {
285:     PetscStrncpy(mach,machine,256);
286:   }

288:   MPI_Comm_rank(v->comm,&rank);
289:   if (!rank) {
290:     PetscLogInfo(0,"PetscViewerSocketSetConnection:Connecting to socket process on port %d machine %sn",port,mach);
291:     SOCKCall_Private(mach,port,&vmatlab->port);
292:   }
293:   return(0);
294: }

296: /* ---------------------------------------------------------------------*/
297: /*
298:     The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
299:   is attached to a communicator, in this case the attribute is a PetscViewer.
300: */
301: static int Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;

303: /*MC
304:   PETSC_VIEWER_SOCKET_WORLD  - same as PETSC_VIEWER_SOCKET_(PETSC_COMM_WORLD)

306:   Level: intermediate
307: M*/

309: /*MC
310:   PETSC_VIEWER_SOCKET_SELF  - same as PETSC_VIEWER_SOCKET_(PETSC_COMM_SELF)

312:   Level: intermediate
313: M*/

315: #undef __FUNCT__  
317: /*@C
318:      PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors 
319:                      in a communicator.

321:      Collective on MPI_Comm

323:      Input Parameter:
324: .    comm - the MPI communicator to share the socket PetscViewer

326:      Level: intermediate

328:    Options Database Keys:
329:    For use with the default Matlab PetscViewer, PETSC_VIEWER_SOCKET_WORLD or if 
330:     PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
331: $    -viewer_socket_machine <machine>
332: $    -viewer_socket_port <port>

334:    Environmental variables:
335: +   PETSC_VIEWER_SOCKET_PORT portnumber
336: -   PETSC_VIEWER_SOCKET_MACHINE machine name

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

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

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

348: .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
349:           PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_()
350: @*/
351: PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm)
352: {
353:   int         ierr;
354:   PetscTruth  flg;
355:   PetscViewer viewer;

358:   if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) {
359:     MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0);
360:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
361:   }
362:   MPI_Attr_get(comm,Petsc_Viewer_Socket_keyval,(void **)&viewer,(int *)&flg);
363:   if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
364:   if (!flg) { /* PetscViewer not yet created */
365:     PetscViewerSocketOpen(comm,0,0,&viewer);
366:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
367:     PetscObjectRegisterDestroy((PetscObject)viewer);
368:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_STDOUT_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
369:     MPI_Attr_put(comm,Petsc_Viewer_Socket_keyval,(void*)viewer);
370:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
371:   }
372:   PetscFunctionReturn(viewer);
373: }

375: #else /* defined (PARCH_win32) */
376: 
377:  #include petscviewer.h
378: #undef __FUNCT__  
380: int PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
381: {
383:   return(0);
384: }
385: #undef __FUNCT__  
387: PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm)
388: {
390:   return(0);
391: }
392: EXTERN_C_BEGIN
393: #undef __FUNCT__  
395: int PetscViewerCreate_Socket(PetscViewer v)
396: {
398:   return(0);
399: }
400: EXTERN_C_END
401: #endif