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: }