#define PETSC_DLL #include "petsc.h" #include "petscsys.h" #if defined(PETSC_NEEDS_UTYPE_TYPEDEFS) /* Some systems have inconsistent include files that use but do not ensure that the following definitions are made */ typedef unsigned char u_char; typedef unsigned short u_short; typedef unsigned short ushort; typedef unsigned int u_int; typedef unsigned long u_long; #endif #include #if defined(PETSC_HAVE_STDLIB_H) #include #endif #include #include #if defined(PETSC_HAVE_MACHINE_ENDIAN_H) #include #endif #if defined(PETSC_HAVE_UNISTD_H) #include #endif #if defined(PETSC_HAVE_SYS_SOCKET_H) #include #endif #if defined(PETSC_HAVE_SYS_WAIT_H) #include #endif #if defined(PETSC_HAVE_NETINET_IN_H) #include #endif #if defined(PETSC_HAVE_NETDB_H) #include #endif #if defined(PETSC_HAVE_FCNTL_H) #include #endif #if defined(PETSC_HAVE_IO_H) #include #endif #if defined(PETSC_HAVE_WINSOCK2_H) #include #endif #include "src/sys/viewer/impls/socket/socket.h" #include "petscfix.h" EXTERN_C_BEGIN #if defined(PETSC_NEED_CLOSE_PROTO) extern int close(int); #endif #if defined(PETSC_NEED_SOCKET_PROTO) extern int socket(int,int,int); #endif #if defined(PETSC_NEED_SLEEP_PROTO) extern int sleep(unsigned); #endif #if defined(PETSC_NEED_CONNECT_PROTO) extern int connect(int,struct sockaddr *,int); #endif EXTERN_C_END /*--------------------------------------------------------------*/ #undef __FUNCT__ #define __FUNCT__ "PetscViewerDestroy_Socket" static PetscErrorCode PetscViewerDestroy_Socket(PetscViewer viewer) { PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data; PetscErrorCode ierr; PetscFunctionBegin; if (vmatlab->port) { #if defined(PETSC_HAVE_CLOSESOCKET) ierr = closesocket(vmatlab->port); #else ierr = close(vmatlab->port); #endif if (ierr) SETERRQ(PETSC_ERR_LIB,"System error closing socket"); } ierr = PetscFree(vmatlab);CHKERRQ(ierr); PetscFunctionReturn(0); } /*--------------------------------------------------------------*/ #undef __FUNCT__ #define __FUNCT__ "SOCKCall_Private" PetscErrorCode PETSC_DLLEXPORT SOCKCall_Private(char *hostname,int portnum,int *t) { struct sockaddr_in sa; struct hostent *hp; int s = 0; PetscErrorCode ierr; PetscTruth flg = PETSC_TRUE; PetscFunctionBegin; if (!(hp=gethostbyname(hostname))) { perror("SEND: error gethostbyname: "); SETERRQ1(PETSC_ERR_LIB,"system error open connection to %s",hostname); } ierr = PetscMemzero(&sa,sizeof(sa));CHKERRQ(ierr); ierr = PetscMemcpy(&sa.sin_addr,hp->h_addr,hp->h_length);CHKERRQ(ierr); sa.sin_family = hp->h_addrtype; sa.sin_port = htons((u_short) portnum); while (flg) { if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) { perror("SEND: error socket"); SETERRQ(PETSC_ERR_LIB,"system error"); } if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) { #if defined(PETSC_HAVE_WSAGETLASTERROR) ierr = WSAGetLastError(); if (ierr == WSAEADDRINUSE) { (*PetscErrorPrintf)("SEND: address is in use\n"); } else if (ierr == WSAEALREADY) { (*PetscErrorPrintf)("SEND: socket is non-blocking \n"); } else if (ierr == WSAEISCONN) { (*PetscErrorPrintf)("SEND: socket already connected\n"); Sleep((unsigned) 1); } else if (ierr == WSAECONNREFUSED) { /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */ Sleep((unsigned) 1); } else { perror(NULL); SETERRQ(PETSC_ERR_LIB,"system error"); } #else if (errno == EADDRINUSE) { (*PetscErrorPrintf)("SEND: address is in use\n"); } else if (errno == EALREADY) { (*PetscErrorPrintf)("SEND: socket is non-blocking \n"); } else if (errno == EISCONN) { (*PetscErrorPrintf)("SEND: socket already connected\n"); sleep((unsigned) 1); } else if (errno == ECONNREFUSED) { /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */ sleep((unsigned) 1); } else { perror(NULL); SETERRQ(PETSC_ERR_LIB,"system error"); } #endif flg = PETSC_TRUE; #if defined(PETSC_HAVE_CLOSESOCKET) closesocket(s); #else close(s); #endif } else flg = PETSC_FALSE; } *t = s; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "PetscViewerSocketOpen" /*@C PetscViewerSocketOpen - Opens a connection to a Matlab or other socket based server. Collective on MPI_Comm Input Parameters: + comm - the MPI communicator . machine - the machine the server is running on - port - the port to connect to, use PETSC_DEFAULT for the default Output Parameter: . lab - a context to use when communicating with the server Level: intermediate Notes: Most users should employ the following commands to access the Matlab PetscViewers $ $ PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer) $ MatView(Mat matrix,PetscViewer viewer) $ $ or $ $ PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer) $ VecView(Vec vector,PetscViewer viewer) Options Database Keys: For use with PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PETSC_VIEWER_SOCKET_() or if PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port $ -viewer_socket_machine $ -viewer_socket_port Environmental variables: + PETSC_VIEWER_SOCKET_PORT portnumber - PETSC_VIEWER_SOCKET_MACHINE machine name Currently the only socket client available is Matlab. See src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage. Concepts: Matlab^sending data Concepts: sockets^sending data .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF @*/ PetscErrorCode PETSC_DLLEXPORT PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab) { PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscViewerCreate(comm,lab);CHKERRQ(ierr); ierr = PetscViewerSetType(*lab,PETSC_VIEWER_SOCKET);CHKERRQ(ierr); ierr = PetscViewerSocketSetConnection(*lab,machine,port);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "PetscViewerSetFromOptions_Socket" PetscErrorCode PetscViewerSetFromOptions_Socket(PetscViewer v) { PetscErrorCode ierr; PetscInt def = -1; char sdef[256]; PetscTruth tflg; PetscFunctionBegin; /* These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they are listed here for the GUI to display */ ierr = PetscOptionsHead("Socket PetscViewer Options");CHKERRQ(ierr); ierr = PetscOptionsGetenv(v->comm,"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);CHKERRQ(ierr); if (tflg) { ierr = PetscOptionsAtoi(sdef,&def);CHKERRQ(ierr); } else { def = DEFAULTPORT; } ierr = PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);CHKERRQ(ierr); ierr = PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);CHKERRQ(ierr); ierr = PetscOptionsGetenv(v->comm,"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);CHKERRQ(ierr); if (!tflg) { ierr = PetscGetHostName(sdef,256);CHKERRQ(ierr); } ierr = PetscOptionsTail();CHKERRQ(ierr); PetscFunctionReturn(0); } EXTERN_C_BEGIN #undef __FUNCT__ #define __FUNCT__ "PetscViewerCreate_Socket" PetscErrorCode PETSC_DLLEXPORT PetscViewerCreate_Socket(PetscViewer v) { PetscViewer_Socket *vmatlab; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscNew(PetscViewer_Socket,&vmatlab);CHKERRQ(ierr); vmatlab->port = 0; v->data = (void*)vmatlab; v->ops->destroy = PetscViewerDestroy_Socket; v->ops->flush = 0; v->ops->setfromoptions = PetscViewerSetFromOptions_Socket; /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */ ierr = PetscObjectChangeTypeName((PetscObject)v,PETSC_VIEWER_BINARY);CHKERRQ(ierr); PetscFunctionReturn(0); } EXTERN_C_END #undef __FUNCT__ #define __FUNCT__ "PetscViewerSocketSetConnection" /*@C PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket viewer is to use Collective on PetscViewer Input Parameters: + v - viewer to connect . machine - host to connect to - port - the port on the machine one is connecting to Level: advanced .seealso: PetscViewerSocketOpen() @*/ PetscErrorCode PETSC_DLLEXPORT PetscViewerSocketSetConnection(PetscViewer v,const char machine[],PetscInt port) { PetscErrorCode ierr; PetscMPIInt rank; char mach[256]; PetscTruth tflg; PetscViewer_Socket *vmatlab = (PetscViewer_Socket *)v->data; PetscFunctionBegin; if (port <= 0) { char portn[16]; ierr = PetscOptionsGetenv(v->comm,"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);CHKERRQ(ierr); if (tflg) { ierr = PetscOptionsAtoi(portn,&port);CHKERRQ(ierr); } else { port = DEFAULTPORT; } } if (!machine) { ierr = PetscOptionsGetenv(v->comm,"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);CHKERRQ(ierr); if (!tflg) { ierr = PetscGetHostName(mach,256);CHKERRQ(ierr); } } else { ierr = PetscStrncpy(mach,machine,256);CHKERRQ(ierr); } ierr = MPI_Comm_rank(v->comm,&rank);CHKERRQ(ierr); if (!rank) { ierr = PetscInfo2(0,"Connecting to socket process on port %D machine %s\n",port,mach);CHKERRQ(ierr); ierr = SOCKCall_Private(mach,(int)port,&vmatlab->port);CHKERRQ(ierr); } PetscFunctionReturn(0); } /* ---------------------------------------------------------------------*/ /* The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that is attached to a communicator, in this case the attribute is a PetscViewer. */ static PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID; #undef __FUNCT__ #define __FUNCT__ "PETSC_VIEWER_SOCKET_" /*@C PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator. Collective on MPI_Comm Input Parameter: . comm - the MPI communicator to share the socket PetscViewer Level: intermediate Options Database Keys: For use with the default Matlab PetscViewer, PETSC_VIEWER_SOCKET_WORLD or if PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port $ -viewer_socket_machine $ -viewer_socket_port Environmental variables: + PETSC_VIEWER_SOCKET_PORT portnumber - PETSC_VIEWER_SOCKET_MACHINE machine name Notes: Unlike almost all other PETSc routines, PetscViewer_SOCKET_ does not return an error code. The socket PetscViewer is usually used in the form $ XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm)); Currently the only socket client available is Matlab. See src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage. Connects to a waiting socket and stays connected until PetscViewerDestroy() is called. .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(), PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_() @*/ PetscViewer PETSC_DLLEXPORT PETSC_VIEWER_SOCKET_(MPI_Comm comm) { PetscErrorCode ierr; PetscTruth flg; PetscViewer viewer; PetscFunctionBegin; if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) { ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0); if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," ");PetscFunctionReturn(0);} } ierr = MPI_Attr_get(comm,Petsc_Viewer_Socket_keyval,(void **)&viewer,(int*)&flg); if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," ");PetscFunctionReturn(0);} if (!flg) { /* PetscViewer not yet created */ ierr = PetscViewerSocketOpen(comm,0,0,&viewer); if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," ");PetscFunctionReturn(0);} ierr = PetscObjectRegisterDestroy((PetscObject)viewer); if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," ");PetscFunctionReturn(0);} ierr = MPI_Attr_put(comm,Petsc_Viewer_Socket_keyval,(void*)viewer); if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," ");PetscFunctionReturn(0);} } PetscFunctionReturn(viewer); }