xref: /petsc/src/sys/classes/viewer/impls/socket/send.c (revision efca3c55b02548817e185e5069a2acfe20fa4458)
15c6c1daeSBarry Smith 
25c6c1daeSBarry Smith #include <petscsys.h>
35c6c1daeSBarry Smith 
45c6c1daeSBarry Smith #if defined(PETSC_NEEDS_UTYPE_TYPEDEFS)
55c6c1daeSBarry Smith /* Some systems have inconsistent include files that use but do not
65c6c1daeSBarry Smith    ensure that the following definitions are made */
75c6c1daeSBarry Smith typedef unsigned char   u_char;
85c6c1daeSBarry Smith typedef unsigned short  u_short;
95c6c1daeSBarry Smith typedef unsigned short  ushort;
105c6c1daeSBarry Smith typedef unsigned int    u_int;
115c6c1daeSBarry Smith typedef unsigned long   u_long;
125c6c1daeSBarry Smith #endif
135c6c1daeSBarry Smith 
145c6c1daeSBarry Smith #include <errno.h>
155c6c1daeSBarry Smith #include <ctype.h>
165c6c1daeSBarry Smith #if defined(PETSC_HAVE_MACHINE_ENDIAN_H)
175c6c1daeSBarry Smith #include <machine/endian.h>
185c6c1daeSBarry Smith #endif
195c6c1daeSBarry Smith #if defined(PETSC_HAVE_UNISTD_H)
205c6c1daeSBarry Smith #include <unistd.h>
215c6c1daeSBarry Smith #endif
225c6c1daeSBarry Smith #if defined(PETSC_HAVE_SYS_SOCKET_H)
235c6c1daeSBarry Smith #include <sys/socket.h>
245c6c1daeSBarry Smith #endif
255c6c1daeSBarry Smith #if defined(PETSC_HAVE_SYS_WAIT_H)
265c6c1daeSBarry Smith #include <sys/wait.h>
275c6c1daeSBarry Smith #endif
285c6c1daeSBarry Smith #if defined(PETSC_HAVE_NETINET_IN_H)
295c6c1daeSBarry Smith #include <netinet/in.h>
305c6c1daeSBarry Smith #endif
315c6c1daeSBarry Smith #if defined(PETSC_HAVE_NETDB_H)
325c6c1daeSBarry Smith #include <netdb.h>
335c6c1daeSBarry Smith #endif
345c6c1daeSBarry Smith #if defined(PETSC_HAVE_FCNTL_H)
355c6c1daeSBarry Smith #include <fcntl.h>
365c6c1daeSBarry Smith #endif
375c6c1daeSBarry Smith #if defined(PETSC_HAVE_IO_H)
385c6c1daeSBarry Smith #include <io.h>
395c6c1daeSBarry Smith #endif
405c6c1daeSBarry Smith #if defined(PETSC_HAVE_WINSOCK2_H)
415c6c1daeSBarry Smith #include <Winsock2.h>
425c6c1daeSBarry Smith #endif
435c6c1daeSBarry Smith #include <sys/stat.h>
445c6c1daeSBarry Smith #include <../src/sys/classes/viewer/impls/socket/socket.h>
455c6c1daeSBarry Smith 
465c6c1daeSBarry Smith #if defined(PETSC_NEED_CLOSE_PROTO)
478cc058d9SJed Brown PETSC_EXTERN int close(int);
485c6c1daeSBarry Smith #endif
495c6c1daeSBarry Smith #if defined(PETSC_NEED_SOCKET_PROTO)
508cc058d9SJed Brown PETSC_EXTERN int socket(int,int,int);
515c6c1daeSBarry Smith #endif
525c6c1daeSBarry Smith #if defined(PETSC_NEED_SLEEP_PROTO)
538cc058d9SJed Brown PETSC_EXTERN int sleep(unsigned);
545c6c1daeSBarry Smith #endif
555c6c1daeSBarry Smith #if defined(PETSC_NEED_CONNECT_PROTO)
568cc058d9SJed Brown PETSC_EXTERN int connect(int,struct sockaddr*,int);
575c6c1daeSBarry Smith #endif
585c6c1daeSBarry Smith 
595c6c1daeSBarry Smith /*--------------------------------------------------------------*/
605c6c1daeSBarry Smith #undef __FUNCT__
615c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerDestroy_Socket"
625c6c1daeSBarry Smith static PetscErrorCode PetscViewerDestroy_Socket(PetscViewer viewer)
635c6c1daeSBarry Smith {
645c6c1daeSBarry Smith   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data;
655c6c1daeSBarry Smith   PetscErrorCode     ierr;
665c6c1daeSBarry Smith 
675c6c1daeSBarry Smith   PetscFunctionBegin;
685c6c1daeSBarry Smith   if (vmatlab->port) {
695c6c1daeSBarry Smith #if defined(PETSC_HAVE_CLOSESOCKET)
705c6c1daeSBarry Smith     ierr = closesocket(vmatlab->port);
715c6c1daeSBarry Smith #else
725c6c1daeSBarry Smith     ierr = close(vmatlab->port);
735c6c1daeSBarry Smith #endif
745c6c1daeSBarry Smith     if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"System error closing socket");
755c6c1daeSBarry Smith   }
765c6c1daeSBarry Smith   ierr = PetscFree(vmatlab);CHKERRQ(ierr);
775c6c1daeSBarry Smith   PetscFunctionReturn(0);
785c6c1daeSBarry Smith }
795c6c1daeSBarry Smith 
805c6c1daeSBarry Smith /*--------------------------------------------------------------*/
815c6c1daeSBarry Smith #undef __FUNCT__
825c6c1daeSBarry Smith #define __FUNCT__ "PetscOpenSocket"
835c6c1daeSBarry Smith /*
845c6c1daeSBarry Smith     PetscSocketOpen - handles connected to an open port where someone is waiting.
855c6c1daeSBarry Smith 
865c6c1daeSBarry Smith .seealso:   PetscSocketListen(), PetscSocketEstablish()
875c6c1daeSBarry Smith */
88e2fc02c1SBarry Smith PetscErrorCode  PetscOpenSocket(const char hostname[],int portnum,int *t)
895c6c1daeSBarry Smith {
905c6c1daeSBarry Smith   struct sockaddr_in sa;
915c6c1daeSBarry Smith   struct hostent     *hp;
925c6c1daeSBarry Smith   int                s = 0;
935c6c1daeSBarry Smith   PetscErrorCode     ierr;
945c6c1daeSBarry Smith   PetscBool          flg = PETSC_TRUE;
955c6c1daeSBarry Smith 
965c6c1daeSBarry Smith   PetscFunctionBegin;
975c6c1daeSBarry Smith   if (!(hp=gethostbyname(hostname))) {
985c6c1daeSBarry Smith     perror("SEND: error gethostbyname: ");
995c6c1daeSBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error open connection to %s",hostname);
1005c6c1daeSBarry Smith   }
1015c6c1daeSBarry Smith   ierr = PetscMemzero(&sa,sizeof(sa));CHKERRQ(ierr);
1025c6c1daeSBarry Smith   ierr = PetscMemcpy(&sa.sin_addr,hp->h_addr_list[0],hp->h_length);CHKERRQ(ierr);
1035c6c1daeSBarry Smith 
1045c6c1daeSBarry Smith   sa.sin_family = hp->h_addrtype;
1055c6c1daeSBarry Smith   sa.sin_port   = htons((u_short) portnum);
1065c6c1daeSBarry Smith   while (flg) {
1075c6c1daeSBarry Smith     if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) {
1085c6c1daeSBarry Smith       perror("SEND: error socket");  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
1095c6c1daeSBarry Smith     }
1105c6c1daeSBarry Smith     if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
1115c6c1daeSBarry Smith #if defined(PETSC_HAVE_WSAGETLASTERROR)
1125c6c1daeSBarry Smith       ierr = WSAGetLastError();
113a297a907SKarl Rupp       if (ierr == WSAEADDRINUSE)    (*PetscErrorPrintf)("SEND: address is in use\n");
114a297a907SKarl Rupp       else if (ierr == WSAEALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
115a297a907SKarl Rupp       else if (ierr == WSAEISCONN) {
1165c6c1daeSBarry Smith         (*PetscErrorPrintf)("SEND: socket already connected\n");
1175c6c1daeSBarry Smith         Sleep((unsigned) 1);
1185c6c1daeSBarry Smith       } else if (ierr == WSAECONNREFUSED) {
1195c6c1daeSBarry Smith         /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */
1205c6c1daeSBarry Smith         Sleep((unsigned) 1);
1215c6c1daeSBarry Smith       } else {
1225c6c1daeSBarry Smith         perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
1235c6c1daeSBarry Smith       }
1245c6c1daeSBarry Smith #else
125a297a907SKarl Rupp       if (errno == EADDRINUSE)    (*PetscErrorPrintf)("SEND: address is in use\n");
126a297a907SKarl Rupp       else if (errno == EALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
127a297a907SKarl Rupp       else if (errno == EISCONN) {
1285c6c1daeSBarry Smith         (*PetscErrorPrintf)("SEND: socket already connected\n");
1295c6c1daeSBarry Smith         sleep((unsigned) 1);
1305c6c1daeSBarry Smith       } else if (errno == ECONNREFUSED) {
1315c6c1daeSBarry Smith         /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */
1325c6c1daeSBarry Smith         ierr = PetscInfo(0,"Connection refused in attaching socket, trying again");CHKERRQ(ierr);
1335c6c1daeSBarry Smith         sleep((unsigned) 1);
1345c6c1daeSBarry Smith       } else {
1355c6c1daeSBarry Smith         perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
1365c6c1daeSBarry Smith       }
1375c6c1daeSBarry Smith #endif
1385c6c1daeSBarry Smith       flg = PETSC_TRUE;
1395c6c1daeSBarry Smith #if defined(PETSC_HAVE_CLOSESOCKET)
1405c6c1daeSBarry Smith       closesocket(s);
1415c6c1daeSBarry Smith #else
1425c6c1daeSBarry Smith       close(s);
1435c6c1daeSBarry Smith #endif
144a297a907SKarl Rupp     } else flg = PETSC_FALSE;
1455c6c1daeSBarry Smith   }
1465c6c1daeSBarry Smith   *t = s;
1475c6c1daeSBarry Smith   PetscFunctionReturn(0);
1485c6c1daeSBarry Smith }
1495c6c1daeSBarry Smith 
1505c6c1daeSBarry Smith #define MAXHOSTNAME 100
1515c6c1daeSBarry Smith #undef __FUNCT__
1525c6c1daeSBarry Smith #define __FUNCT__ "PetscSocketEstablish"
1535c6c1daeSBarry Smith /*
1545c6c1daeSBarry Smith    PetscSocketEstablish - starts a listener on a socket
1555c6c1daeSBarry Smith 
1565c6c1daeSBarry Smith .seealso:   PetscSocketListen()
1575c6c1daeSBarry Smith */
1585847ff97SBarry Smith PETSC_INTERN PetscErrorCode PetscSocketEstablish(int portnum,int *ss)
1595c6c1daeSBarry Smith {
1605c6c1daeSBarry Smith   char               myname[MAXHOSTNAME+1];
1615c6c1daeSBarry Smith   int                s;
1625c6c1daeSBarry Smith   PetscErrorCode     ierr;
1635c6c1daeSBarry Smith   struct sockaddr_in sa;
1645c6c1daeSBarry Smith   struct hostent     *hp;
1655c6c1daeSBarry Smith 
1665c6c1daeSBarry Smith   PetscFunctionBegin;
1675c6c1daeSBarry Smith   ierr = PetscGetHostName(myname,MAXHOSTNAME);CHKERRQ(ierr);
1685c6c1daeSBarry Smith 
1695c6c1daeSBarry Smith   ierr = PetscMemzero(&sa,sizeof(struct sockaddr_in));CHKERRQ(ierr);
1705c6c1daeSBarry Smith 
1715c6c1daeSBarry Smith   hp = gethostbyname(myname);
1725c6c1daeSBarry Smith   if (!hp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Unable to get hostent information from system");
1735c6c1daeSBarry Smith 
1745c6c1daeSBarry Smith   sa.sin_family = hp->h_addrtype;
1755c6c1daeSBarry Smith   sa.sin_port   = htons((u_short)portnum);
1765c6c1daeSBarry Smith 
1775c6c1daeSBarry Smith   if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error running socket() command");
1785c6c1daeSBarry Smith #if defined(PETSC_HAVE_SO_REUSEADDR)
1795c6c1daeSBarry Smith   {
1805c6c1daeSBarry Smith     int optval = 1; /* Turn on the option */
1815c6c1daeSBarry Smith     ierr = setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&optval,sizeof(optval));CHKERRQ(ierr);
1825c6c1daeSBarry Smith   }
1835c6c1daeSBarry Smith #endif
1845c6c1daeSBarry Smith 
1855c6c1daeSBarry Smith   while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
1865c6c1daeSBarry Smith #if defined(PETSC_HAVE_WSAGETLASTERROR)
1875c6c1daeSBarry Smith     ierr = WSAGetLastError();
1885c6c1daeSBarry Smith     if (ierr != WSAEADDRINUSE) {
1895c6c1daeSBarry Smith #else
1905c6c1daeSBarry Smith     if (errno != EADDRINUSE) {
1915c6c1daeSBarry Smith #endif
1925c6c1daeSBarry Smith       close(s);
1935c6c1daeSBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error from bind()");
1945c6c1daeSBarry Smith     }
1955c6c1daeSBarry Smith   }
1965c6c1daeSBarry Smith   listen(s,0);
1975c6c1daeSBarry Smith   *ss = s;
1985c6c1daeSBarry Smith   return(0);
1995c6c1daeSBarry Smith }
2005c6c1daeSBarry Smith 
2015c6c1daeSBarry Smith #undef __FUNCT__
2025c6c1daeSBarry Smith #define __FUNCT__ "PetscSocketListen"
2035c6c1daeSBarry Smith /*
2045c6c1daeSBarry Smith    PetscSocketListens - Listens at a socket created with PetscSocketEstablish()
2055c6c1daeSBarry Smith 
2065c6c1daeSBarry Smith .seealso:   PetscSocketEstablish()
2075c6c1daeSBarry Smith */
2085847ff97SBarry Smith PETSC_INTERN PetscErrorCode PetscSocketListen(int listenport,int *t)
2095c6c1daeSBarry Smith {
2105c6c1daeSBarry Smith   struct sockaddr_in isa;
2115c6c1daeSBarry Smith #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
2125c6c1daeSBarry Smith   size_t             i;
2135c6c1daeSBarry Smith #else
2145c6c1daeSBarry Smith   int                i;
2155c6c1daeSBarry Smith #endif
2165c6c1daeSBarry Smith 
2175c6c1daeSBarry Smith   PetscFunctionBegin;
2185c6c1daeSBarry Smith   /* wait for someone to try to connect */
2195c6c1daeSBarry Smith   i = sizeof(struct sockaddr_in);
2205c6c1daeSBarry Smith   if ((*t = accept(listenport,(struct sockaddr*)&isa,(socklen_t*)&i)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"error from accept()\n");
2215c6c1daeSBarry Smith   PetscFunctionReturn(0);
2225c6c1daeSBarry Smith }
2235c6c1daeSBarry Smith 
2245c6c1daeSBarry Smith #undef __FUNCT__
2255c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerSocketOpen"
2265c6c1daeSBarry Smith /*@C
2275c6c1daeSBarry Smith    PetscViewerSocketOpen - Opens a connection to a MATLAB or other socket
2285c6c1daeSBarry Smith         based server.
2295c6c1daeSBarry Smith 
2305c6c1daeSBarry Smith    Collective on MPI_Comm
2315c6c1daeSBarry Smith 
2325c6c1daeSBarry Smith    Input Parameters:
2335c6c1daeSBarry Smith +  comm - the MPI communicator
2340298fd71SBarry Smith .  machine - the machine the server is running on,, use NULL for the local machine, use "server" to passively wait for
2355c6c1daeSBarry Smith              a connection from elsewhere
2365c6c1daeSBarry Smith -  port - the port to connect to, use PETSC_DEFAULT for the default
2375c6c1daeSBarry Smith 
2385c6c1daeSBarry Smith    Output Parameter:
2395c6c1daeSBarry Smith .  lab - a context to use when communicating with the server
2405c6c1daeSBarry Smith 
2415c6c1daeSBarry Smith    Level: intermediate
2425c6c1daeSBarry Smith 
2435c6c1daeSBarry Smith    Notes:
2445c6c1daeSBarry Smith    Most users should employ the following commands to access the
2455c6c1daeSBarry Smith    MATLAB PetscViewers
2465c6c1daeSBarry Smith $
2475c6c1daeSBarry Smith $    PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
2485c6c1daeSBarry Smith $    MatView(Mat matrix,PetscViewer viewer)
2495c6c1daeSBarry Smith $
2505c6c1daeSBarry Smith $                or
2515c6c1daeSBarry Smith $
2525c6c1daeSBarry Smith $    PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
2535c6c1daeSBarry Smith $    VecView(Vec vector,PetscViewer viewer)
2545c6c1daeSBarry Smith 
2555c6c1daeSBarry Smith    Options Database Keys:
2565c6c1daeSBarry Smith    For use with  PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
2575c6c1daeSBarry Smith    PETSC_VIEWER_SOCKET_() or if
2580298fd71SBarry Smith     NULL is passed for machine or PETSC_DEFAULT is passed for port
2595c6c1daeSBarry Smith $    -viewer_socket_machine <machine>
2605c6c1daeSBarry Smith $    -viewer_socket_port <port>
2615c6c1daeSBarry Smith 
2625c6c1daeSBarry Smith    Environmental variables:
2635c6c1daeSBarry Smith +   PETSC_VIEWER_SOCKET_PORT portnumber
2645c6c1daeSBarry Smith -   PETSC_VIEWER_SOCKET_MACHINE machine name
2655c6c1daeSBarry Smith 
2665c6c1daeSBarry Smith      Currently the only socket client available is MATLAB. See
2675c6c1daeSBarry Smith      src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.
2685c6c1daeSBarry Smith 
2695c6c1daeSBarry Smith    Notes: The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket
2705c6c1daeSBarry Smith           use PetscViewerBinaryRead/Write/GetDescriptor().
2715c6c1daeSBarry Smith 
2725c6c1daeSBarry Smith    Concepts: MATLAB^sending data
2735c6c1daeSBarry Smith    Concepts: sockets^sending data
2745c6c1daeSBarry Smith 
2755c6c1daeSBarry Smith .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
2765c6c1daeSBarry Smith           PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD,
2775c6c1daeSBarry Smith           PETSC_VIEWER_SOCKET_SELF, PetscViewerBinaryWrite(), PetscViewerBinaryRead(), PetscViewerBinaryWriteStringArray(),
2785c6c1daeSBarry Smith           PetscBinaryViewerGetDescriptor()
2795c6c1daeSBarry Smith @*/
2805c6c1daeSBarry Smith PetscErrorCode  PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
2815c6c1daeSBarry Smith {
2825c6c1daeSBarry Smith   PetscErrorCode ierr;
2835c6c1daeSBarry Smith 
2845c6c1daeSBarry Smith   PetscFunctionBegin;
2855c6c1daeSBarry Smith   ierr = PetscViewerCreate(comm,lab);CHKERRQ(ierr);
2865c6c1daeSBarry Smith   ierr = PetscViewerSetType(*lab,PETSCVIEWERSOCKET);CHKERRQ(ierr);
2875c6c1daeSBarry Smith   ierr = PetscViewerSocketSetConnection(*lab,machine,port);CHKERRQ(ierr);
2885c6c1daeSBarry Smith   PetscFunctionReturn(0);
2895c6c1daeSBarry Smith }
2905c6c1daeSBarry Smith 
2915c6c1daeSBarry Smith #undef __FUNCT__
2925c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerSetFromOptions_Socket"
293242ebda1SBarry Smith static PetscErrorCode PetscViewerSetFromOptions_Socket(PetscViewer v)
2945c6c1daeSBarry Smith {
2955c6c1daeSBarry Smith   PetscErrorCode ierr;
2965c6c1daeSBarry Smith   PetscInt       def = -1;
2975c6c1daeSBarry Smith   char           sdef[256];
2985c6c1daeSBarry Smith   PetscBool      tflg;
2995c6c1daeSBarry Smith 
3005c6c1daeSBarry Smith   PetscFunctionBegin;
3015c6c1daeSBarry Smith   /*
3025c6c1daeSBarry Smith        These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
3035c6c1daeSBarry Smith     are listed here for the GUI to display
3045c6c1daeSBarry Smith   */
3055c6c1daeSBarry Smith   ierr = PetscOptionsHead("Socket PetscViewer Options");CHKERRQ(ierr);
306ce94432eSBarry Smith   ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);CHKERRQ(ierr);
3075c6c1daeSBarry Smith   if (tflg) {
3085c6c1daeSBarry Smith     ierr = PetscOptionsStringToInt(sdef,&def);CHKERRQ(ierr);
309a297a907SKarl Rupp   } else def = PETSCSOCKETDEFAULTPORT;
3105c6c1daeSBarry Smith   ierr = PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);CHKERRQ(ierr);
3115c6c1daeSBarry Smith 
3125c6c1daeSBarry Smith   ierr = PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);CHKERRQ(ierr);
313ce94432eSBarry Smith   ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);CHKERRQ(ierr);
3145c6c1daeSBarry Smith   if (!tflg) {
3155c6c1daeSBarry Smith     ierr = PetscGetHostName(sdef,256);CHKERRQ(ierr);
3165c6c1daeSBarry Smith   }
3175c6c1daeSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
3185c6c1daeSBarry Smith   PetscFunctionReturn(0);
3195c6c1daeSBarry Smith }
3205c6c1daeSBarry Smith 
3215c6c1daeSBarry Smith #undef __FUNCT__
3225c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerCreate_Socket"
3238cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PetscViewerCreate_Socket(PetscViewer v)
3245c6c1daeSBarry Smith {
3255c6c1daeSBarry Smith   PetscViewer_Socket *vmatlab;
3265c6c1daeSBarry Smith   PetscErrorCode     ierr;
3275c6c1daeSBarry Smith 
3285c6c1daeSBarry Smith   PetscFunctionBegin;
3295c6c1daeSBarry Smith   ierr                   = PetscNewLog(v,PetscViewer_Socket,&vmatlab);CHKERRQ(ierr);
3305c6c1daeSBarry Smith   vmatlab->port          = 0;
3315c6c1daeSBarry Smith   v->data                = (void*)vmatlab;
3325c6c1daeSBarry Smith   v->ops->destroy        = PetscViewerDestroy_Socket;
3335c6c1daeSBarry Smith   v->ops->flush          = 0;
3345c6c1daeSBarry Smith   v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;
3355c6c1daeSBarry Smith 
3365c6c1daeSBarry Smith   /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */
3375c6c1daeSBarry Smith   ierr                   = PetscObjectChangeTypeName((PetscObject)v,PETSCVIEWERBINARY);CHKERRQ(ierr);
3385c6c1daeSBarry Smith   PetscFunctionReturn(0);
3395c6c1daeSBarry Smith }
3405c6c1daeSBarry Smith 
3415c6c1daeSBarry Smith #undef __FUNCT__
3425c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerSocketSetConnection"
3435c6c1daeSBarry Smith /*@C
3445c6c1daeSBarry Smith       PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket
3455c6c1daeSBarry Smith              viewer is to use
3465c6c1daeSBarry Smith 
3475c6c1daeSBarry Smith   Logically Collective on PetscViewer
3485c6c1daeSBarry Smith 
3495c6c1daeSBarry Smith   Input Parameters:
3505c6c1daeSBarry Smith +   v - viewer to connect
3510298fd71SBarry Smith .   machine - host to connect to, use NULL for the local machine,use "server" to passively wait for
3525c6c1daeSBarry Smith              a connection from elsewhere
3535c6c1daeSBarry Smith -   port - the port on the machine one is connecting to, use PETSC_DEFAULT for default
3545c6c1daeSBarry Smith 
3555c6c1daeSBarry Smith     Level: advanced
3565c6c1daeSBarry Smith 
3575c6c1daeSBarry Smith .seealso: PetscViewerSocketOpen()
3585c6c1daeSBarry Smith @*/
3595c6c1daeSBarry Smith PetscErrorCode  PetscViewerSocketSetConnection(PetscViewer v,const char machine[],int port)
3605c6c1daeSBarry Smith {
3615c6c1daeSBarry Smith   PetscErrorCode     ierr;
3625c6c1daeSBarry Smith   PetscMPIInt        rank;
3635c6c1daeSBarry Smith   char               mach[256];
3645c6c1daeSBarry Smith   PetscBool          tflg;
3655c6c1daeSBarry Smith   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)v->data;
3665c6c1daeSBarry Smith 
3675c6c1daeSBarry Smith   PetscFunctionBegin;
3685c6c1daeSBarry Smith   /* PetscValidLogicalCollectiveInt(v,port,3); not a PetscInt */
3695c6c1daeSBarry Smith   if (port <= 0) {
3705c6c1daeSBarry Smith     char portn[16];
371ce94432eSBarry Smith     ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);CHKERRQ(ierr);
3725c6c1daeSBarry Smith     if (tflg) {
3735c6c1daeSBarry Smith       PetscInt pport;
3745c6c1daeSBarry Smith       ierr = PetscOptionsStringToInt(portn,&pport);CHKERRQ(ierr);
3755c6c1daeSBarry Smith       port = (int)pport;
376a297a907SKarl Rupp     } else port = PETSCSOCKETDEFAULTPORT;
3775c6c1daeSBarry Smith   }
3785c6c1daeSBarry Smith   if (!machine) {
379ce94432eSBarry Smith     ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);CHKERRQ(ierr);
3805c6c1daeSBarry Smith     if (!tflg) {
3815c6c1daeSBarry Smith       ierr = PetscGetHostName(mach,256);CHKERRQ(ierr);
3825c6c1daeSBarry Smith     }
3835c6c1daeSBarry Smith   } else {
3845c6c1daeSBarry Smith     ierr = PetscStrncpy(mach,machine,256);CHKERRQ(ierr);
3855c6c1daeSBarry Smith   }
3865c6c1daeSBarry Smith 
387ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)v),&rank);CHKERRQ(ierr);
3885c6c1daeSBarry Smith   if (!rank) {
3895c6c1daeSBarry Smith     ierr = PetscStrcmp(mach,"server",&tflg);CHKERRQ(ierr);
3905c6c1daeSBarry Smith     if (tflg) {
3915c6c1daeSBarry Smith       int listenport;
3925c6c1daeSBarry Smith       ierr = PetscInfo1(v,"Waiting for connection from socket process on port %D\n",port);CHKERRQ(ierr);
3935c6c1daeSBarry Smith       ierr = PetscSocketEstablish(port,&listenport);CHKERRQ(ierr);
3945c6c1daeSBarry Smith       ierr = PetscSocketListen(listenport,&vmatlab->port);CHKERRQ(ierr);
3955c6c1daeSBarry Smith       close(listenport);
3965c6c1daeSBarry Smith     } else {
3975c6c1daeSBarry Smith       ierr = PetscInfo2(v,"Connecting to socket process on port %D machine %s\n",port,mach);CHKERRQ(ierr);
3985c6c1daeSBarry Smith       ierr = PetscOpenSocket(mach,port,&vmatlab->port);CHKERRQ(ierr);
3995c6c1daeSBarry Smith     }
4005c6c1daeSBarry Smith   }
4015c6c1daeSBarry Smith   PetscFunctionReturn(0);
4025c6c1daeSBarry Smith }
4035c6c1daeSBarry Smith 
4045c6c1daeSBarry Smith /* ---------------------------------------------------------------------*/
4055c6c1daeSBarry Smith /*
4065c6c1daeSBarry Smith     The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
4075c6c1daeSBarry Smith   is attached to a communicator, in this case the attribute is a PetscViewer.
4085c6c1daeSBarry Smith */
4095c6c1daeSBarry Smith static PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;
4105c6c1daeSBarry Smith 
4115c6c1daeSBarry Smith 
4125c6c1daeSBarry Smith #undef __FUNCT__
4135c6c1daeSBarry Smith #define __FUNCT__ "PETSC_VIEWER_SOCKET_"
4145c6c1daeSBarry Smith /*@C
4155c6c1daeSBarry Smith      PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator.
4165c6c1daeSBarry Smith 
4175c6c1daeSBarry Smith      Collective on MPI_Comm
4185c6c1daeSBarry Smith 
4195c6c1daeSBarry Smith      Input Parameter:
4205c6c1daeSBarry Smith .    comm - the MPI communicator to share the socket PetscViewer
4215c6c1daeSBarry Smith 
4225c6c1daeSBarry Smith      Level: intermediate
4235c6c1daeSBarry Smith 
4245c6c1daeSBarry Smith    Options Database Keys:
4255c6c1daeSBarry Smith    For use with the default PETSC_VIEWER_SOCKET_WORLD or if
4260298fd71SBarry Smith     NULL is passed for machine or PETSC_DEFAULT is passed for port
4275c6c1daeSBarry Smith $    -viewer_socket_machine <machine>
4285c6c1daeSBarry Smith $    -viewer_socket_port <port>
4295c6c1daeSBarry Smith 
4305c6c1daeSBarry Smith    Environmental variables:
4315c6c1daeSBarry Smith +   PETSC_VIEWER_SOCKET_PORT portnumber
4325c6c1daeSBarry Smith -   PETSC_VIEWER_SOCKET_MACHINE machine name
4335c6c1daeSBarry Smith 
4345c6c1daeSBarry Smith      Notes:
4355c6c1daeSBarry Smith      Unlike almost all other PETSc routines, PetscViewer_SOCKET_ does not return
4365c6c1daeSBarry Smith      an error code.  The socket PetscViewer is usually used in the form
4375c6c1daeSBarry Smith $       XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm));
4385c6c1daeSBarry Smith 
4395c6c1daeSBarry Smith      Currently the only socket client available is MATLAB. See
4405c6c1daeSBarry Smith      src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.
4415c6c1daeSBarry Smith 
4425c6c1daeSBarry Smith      Connects to a waiting socket and stays connected until PetscViewerDestroy() is called.
4435c6c1daeSBarry Smith 
4445c6c1daeSBarry Smith      Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for communicating with the MATLAB engine.
4455c6c1daeSBarry Smith 
4465c6c1daeSBarry Smith .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
4475c6c1daeSBarry Smith           PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(),
4485c6c1daeSBarry Smith           PetscViewerBinaryWriteStringArray(), PetscBinaryViewerGetDescriptor(), PETSC_VIEWER_MATLAB_()
4495c6c1daeSBarry Smith @*/
4505c6c1daeSBarry Smith PetscViewer  PETSC_VIEWER_SOCKET_(MPI_Comm comm)
4515c6c1daeSBarry Smith {
4525c6c1daeSBarry Smith   PetscErrorCode ierr;
4535c6c1daeSBarry Smith   PetscBool      flg;
4545c6c1daeSBarry Smith   PetscViewer    viewer;
4555c6c1daeSBarry Smith   MPI_Comm       ncomm;
4565c6c1daeSBarry Smith 
4575c6c1daeSBarry Smith   PetscFunctionBegin;
458*efca3c55SSatish Balay   ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4595c6c1daeSBarry Smith   if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) {
4605c6c1daeSBarry Smith     ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0);
461*efca3c55SSatish Balay     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4625c6c1daeSBarry Smith   }
4635c6c1daeSBarry Smith   ierr = MPI_Attr_get(ncomm,Petsc_Viewer_Socket_keyval,(void**)&viewer,(int*)&flg);
464*efca3c55SSatish Balay   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4655c6c1daeSBarry Smith   if (!flg) { /* PetscViewer not yet created */
4665c6c1daeSBarry Smith     ierr = PetscViewerSocketOpen(ncomm,0,0,&viewer);
467*efca3c55SSatish Balay     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4685c6c1daeSBarry Smith     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
469*efca3c55SSatish Balay     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4705c6c1daeSBarry Smith     ierr = MPI_Attr_put(ncomm,Petsc_Viewer_Socket_keyval,(void*)viewer);
471*efca3c55SSatish Balay     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4725c6c1daeSBarry Smith   }
4735c6c1daeSBarry Smith   ierr = PetscCommDestroy(&ncomm);
474*efca3c55SSatish Balay   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
4755c6c1daeSBarry Smith   PetscFunctionReturn(viewer);
4765c6c1daeSBarry Smith }
4775c6c1daeSBarry Smith 
478