1 2 #include <petscsys.h> 3 4 #if defined(PETSC_NEEDS_UTYPE_TYPEDEFS) 5 /* Some systems have inconsistent include files that use but do not 6 ensure that the following definitions are made */ 7 typedef unsigned char u_char; 8 typedef unsigned short u_short; 9 typedef unsigned short ushort; 10 typedef unsigned int u_int; 11 typedef unsigned long u_long; 12 #endif 13 14 #include <errno.h> 15 #include <ctype.h> 16 #if defined(PETSC_HAVE_MACHINE_ENDIAN_H) 17 #include <machine/endian.h> 18 #endif 19 #if defined(PETSC_HAVE_UNISTD_H) 20 #include <unistd.h> 21 #endif 22 #if defined(PETSC_HAVE_SYS_SOCKET_H) 23 #include <sys/socket.h> 24 #endif 25 #if defined(PETSC_HAVE_SYS_WAIT_H) 26 #include <sys/wait.h> 27 #endif 28 #if defined(PETSC_HAVE_NETINET_IN_H) 29 #include <netinet/in.h> 30 #endif 31 #if defined(PETSC_HAVE_NETDB_H) 32 #include <netdb.h> 33 #endif 34 #if defined(PETSC_HAVE_FCNTL_H) 35 #include <fcntl.h> 36 #endif 37 #if defined(PETSC_HAVE_IO_H) 38 #include <io.h> 39 #endif 40 #if defined(PETSC_HAVE_WINSOCK2_H) 41 #include <Winsock2.h> 42 #endif 43 #include <sys/stat.h> 44 #include <../src/sys/classes/viewer/impls/socket/socket.h> 45 46 #if defined(PETSC_NEED_CLOSE_PROTO) 47 PETSC_EXTERN int close(int); 48 #endif 49 #if defined(PETSC_NEED_SOCKET_PROTO) 50 PETSC_EXTERN int socket(int,int,int); 51 #endif 52 #if defined(PETSC_NEED_SLEEP_PROTO) 53 PETSC_EXTERN int sleep(unsigned); 54 #endif 55 #if defined(PETSC_NEED_CONNECT_PROTO) 56 PETSC_EXTERN int connect(int,struct sockaddr*,int); 57 #endif 58 59 /*--------------------------------------------------------------*/ 60 static PetscErrorCode PetscViewerDestroy_Socket(PetscViewer viewer) 61 { 62 PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data; 63 PetscErrorCode ierr; 64 65 PetscFunctionBegin; 66 if (vmatlab->port) { 67 #if defined(PETSC_HAVE_CLOSESOCKET) 68 ierr = closesocket(vmatlab->port); 69 #else 70 ierr = close(vmatlab->port); 71 #endif 72 if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"System error closing socket"); 73 } 74 ierr = PetscFree(vmatlab);CHKERRQ(ierr); 75 PetscFunctionReturn(0); 76 } 77 78 /*--------------------------------------------------------------*/ 79 /*@C 80 PetscSocketOpen - handles connected to an open port where someone is waiting. 81 82 Input Parameters: 83 + url - for example www.mcs.anl.gov 84 - portnum - for example 80 85 86 Output Paramater: 87 . t - the socket number 88 89 Notes: Use close() to close the socket connection 90 91 Use read() or PetscHTTPRequest() to read from the socket 92 93 Level: advanced 94 95 .seealso: PetscSocketListen(), PetscSocketEstablish(), PetscHTTPRequest(), PetscHTTPSConnect() 96 @*/ 97 PetscErrorCode PetscOpenSocket(const char hostname[],int portnum,int *t) 98 { 99 struct sockaddr_in sa; 100 struct hostent *hp; 101 int s = 0; 102 PetscErrorCode ierr; 103 PetscBool flg = PETSC_TRUE; 104 static int refcnt = 0; 105 106 PetscFunctionBegin; 107 if (!(hp=gethostbyname(hostname))) { 108 perror("SEND: error gethostbyname: "); 109 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error open connection to %s",hostname); 110 } 111 ierr = PetscMemzero(&sa,sizeof(sa));CHKERRQ(ierr); 112 ierr = PetscMemcpy(&sa.sin_addr,hp->h_addr_list[0],hp->h_length);CHKERRQ(ierr); 113 114 sa.sin_family = hp->h_addrtype; 115 sa.sin_port = htons((u_short) portnum); 116 while (flg) { 117 if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) { 118 perror("SEND: error socket"); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error"); 119 } 120 if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) { 121 #if defined(PETSC_HAVE_WSAGETLASTERROR) 122 ierr = WSAGetLastError(); 123 if (ierr == WSAEADDRINUSE) (*PetscErrorPrintf)("SEND: address is in use\n"); 124 else if (ierr == WSAEALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n"); 125 else if (ierr == WSAEISCONN) { 126 (*PetscErrorPrintf)("SEND: socket already connected\n"); 127 Sleep((unsigned) 1); 128 } else if (ierr == WSAECONNREFUSED) { 129 /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */ 130 Sleep((unsigned) 1); 131 } else { 132 perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error"); 133 } 134 #else 135 if (errno == EADDRINUSE) (*PetscErrorPrintf)("SEND: address is in use\n"); 136 else if (errno == EALREADY) (*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 refcnt++; 142 if (refcnt > 5) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SYS,"Connection refused by remote host %s port %d",hostname,portnum); 143 ierr = PetscInfo(0,"Connection refused in attaching socket, trying again\n");CHKERRQ(ierr); 144 sleep((unsigned) 1); 145 } else { 146 perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error"); 147 } 148 #endif 149 flg = PETSC_TRUE; 150 #if defined(PETSC_HAVE_CLOSESOCKET) 151 closesocket(s); 152 #else 153 close(s); 154 #endif 155 } else flg = PETSC_FALSE; 156 } 157 *t = s; 158 PetscFunctionReturn(0); 159 } 160 161 #define MAXHOSTNAME 100 162 /*@C 163 PetscSocketEstablish - starts a listener on a socket 164 165 Input Parameters: 166 . portnumber - the port to wait at 167 168 Output Parameters: 169 . ss - the socket to be used with PetscSocketListen() 170 171 Level: advanced 172 173 .seealso: PetscSocketListen(), PetscOpenSocket() 174 175 @*/ 176 PETSC_INTERN PetscErrorCode PetscSocketEstablish(int portnum,int *ss) 177 { 178 char myname[MAXHOSTNAME+1]; 179 int s; 180 PetscErrorCode ierr; 181 struct sockaddr_in sa; 182 struct hostent *hp; 183 184 PetscFunctionBegin; 185 ierr = PetscGetHostName(myname,MAXHOSTNAME);CHKERRQ(ierr); 186 187 ierr = PetscMemzero(&sa,sizeof(struct sockaddr_in));CHKERRQ(ierr); 188 189 hp = gethostbyname(myname); 190 if (!hp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Unable to get hostent information from system"); 191 192 sa.sin_family = hp->h_addrtype; 193 sa.sin_port = htons((u_short)portnum); 194 195 if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error running socket() command"); 196 #if defined(PETSC_HAVE_SO_REUSEADDR) 197 { 198 int optval = 1; /* Turn on the option */ 199 ierr = setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&optval,sizeof(optval));CHKERRQ(ierr); 200 } 201 #endif 202 203 while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) { 204 #if defined(PETSC_HAVE_WSAGETLASTERROR) 205 ierr = WSAGetLastError(); 206 if (ierr != WSAEADDRINUSE) { 207 #else 208 if (errno != EADDRINUSE) { 209 #endif 210 close(s); 211 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error from bind()"); 212 } 213 } 214 listen(s,0); 215 *ss = s; 216 return(0); 217 } 218 219 /*@C 220 PetscSocketListen - Listens at a socket created with PetscSocketEstablish() 221 222 Input Parameter: 223 . listenport - obtained with PetscSocketEstablish() 224 225 Output Parameter: 226 . t - pass this to read() to read what is passed to this connection 227 228 Level: advanced 229 230 .seealso: PetscSocketEstablish() 231 @*/ 232 PETSC_INTERN PetscErrorCode PetscSocketListen(int listenport,int *t) 233 { 234 struct sockaddr_in isa; 235 #if defined(PETSC_HAVE_ACCEPT_SIZE_T) 236 size_t i; 237 #else 238 int i; 239 #endif 240 241 PetscFunctionBegin; 242 /* wait for someone to try to connect */ 243 i = sizeof(struct sockaddr_in); 244 if ((*t = accept(listenport,(struct sockaddr*)&isa,(socklen_t*)&i)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"error from accept()\n"); 245 PetscFunctionReturn(0); 246 } 247 248 /*@C 249 PetscViewerSocketOpen - Opens a connection to a MATLAB or other socket based server. 250 251 Collective on MPI_Comm 252 253 Input Parameters: 254 + comm - the MPI communicator 255 . machine - the machine the server is running on,, use NULL for the local machine, use "server" to passively wait for 256 a connection from elsewhere 257 - port - the port to connect to, use PETSC_DEFAULT for the default 258 259 Output Parameter: 260 . lab - a context to use when communicating with the server 261 262 Level: intermediate 263 264 Notes: 265 Most users should employ the following commands to access the 266 MATLAB PetscViewers 267 $ 268 $ PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer) 269 $ MatView(Mat matrix,PetscViewer viewer) 270 $ 271 $ or 272 $ 273 $ PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer) 274 $ VecView(Vec vector,PetscViewer viewer) 275 276 Options Database Keys: 277 For use with PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, 278 PETSC_VIEWER_SOCKET_() or if 279 NULL is passed for machine or PETSC_DEFAULT is passed for port 280 $ -viewer_socket_machine <machine> 281 $ -viewer_socket_port <port> 282 283 Environmental variables: 284 + PETSC_VIEWER_SOCKET_PORT portnumber 285 - PETSC_VIEWER_SOCKET_MACHINE machine name 286 287 Currently the only socket client available is MATLAB. See 288 src/dm/examples/tests/ex12.c and ex12.m for an example of usage. 289 290 Notes: The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket 291 use PetscViewerBinaryRead(), PetscViewerBinaryWrite(), PetscViewerBinarWriteStringArray(), PetscViewerBinaryGetDescriptor(). 292 293 Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for writing output to a 294 .mat file. Use PetscMatlabEngineCreate() or PETSC_MATLAB_ENGINE_(), PETSC_MATLAB_ENGINE_SELF, or PETSC_MATLAB_ENGINE_WORLD 295 for communicating with a MATLAB Engine 296 297 Concepts: MATLAB^sending data 298 Concepts: sockets^sending data 299 300 .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(), 301 PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD, 302 PETSC_VIEWER_SOCKET_SELF, PetscViewerBinaryWrite(), PetscViewerBinaryRead(), PetscViewerBinaryWriteStringArray(), 303 PetscBinaryViewerGetDescriptor(), PetscMatlabEngineCreate() 304 @*/ 305 PetscErrorCode PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab) 306 { 307 PetscErrorCode ierr; 308 309 PetscFunctionBegin; 310 ierr = PetscViewerCreate(comm,lab);CHKERRQ(ierr); 311 ierr = PetscViewerSetType(*lab,PETSCVIEWERSOCKET);CHKERRQ(ierr); 312 ierr = PetscViewerSocketSetConnection(*lab,machine,port);CHKERRQ(ierr); 313 PetscFunctionReturn(0); 314 } 315 316 static PetscErrorCode PetscViewerSetFromOptions_Socket(PetscOptionItems *PetscOptionsObject,PetscViewer v) 317 { 318 PetscErrorCode ierr; 319 PetscInt def = -1; 320 char sdef[256]; 321 PetscBool tflg; 322 323 PetscFunctionBegin; 324 /* 325 These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they 326 are listed here for the GUI to display 327 */ 328 ierr = PetscOptionsHead(PetscOptionsObject,"Socket PetscViewer Options");CHKERRQ(ierr); 329 ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);CHKERRQ(ierr); 330 if (tflg) { 331 ierr = PetscOptionsStringToInt(sdef,&def);CHKERRQ(ierr); 332 } else def = PETSCSOCKETDEFAULTPORT; 333 ierr = PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);CHKERRQ(ierr); 334 335 ierr = PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);CHKERRQ(ierr); 336 ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);CHKERRQ(ierr); 337 if (!tflg) { 338 ierr = PetscGetHostName(sdef,256);CHKERRQ(ierr); 339 } 340 ierr = PetscOptionsTail();CHKERRQ(ierr); 341 PetscFunctionReturn(0); 342 } 343 344 static PetscErrorCode PetscViewerBinaryGetSkipHeader_Socket(PetscViewer viewer,PetscBool *skip) 345 { 346 PetscViewer_Socket *vsocket = (PetscViewer_Socket*)viewer->data; 347 348 PetscFunctionBegin; 349 *skip = vsocket->skipheader; 350 PetscFunctionReturn(0); 351 } 352 353 static PetscErrorCode PetscViewerBinarySetSkipHeader_Socket(PetscViewer viewer,PetscBool skip) 354 { 355 PetscViewer_Socket *vsocket = (PetscViewer_Socket*)viewer->data; 356 357 PetscFunctionBegin; 358 vsocket->skipheader = skip; 359 PetscFunctionReturn(0); 360 } 361 362 static PetscErrorCode PetscViewerBinaryGetFlowControl_Socket(PetscViewer viewer,PetscInt *fc) 363 { 364 PetscFunctionBegin; 365 *fc = 0; 366 PetscFunctionReturn(0); 367 } 368 369 /*MC 370 PETSCVIEWERSOCKET - A viewer that writes to a Unix socket 371 372 373 .seealso: PetscViewerSocketOpen(), PetscViewerDrawOpen(), PETSC_VIEWER_DRAW_(),PETSC_VIEWER_DRAW_SELF, PETSC_VIEWER_DRAW_WORLD, 374 PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY, PETSCVIEWERDRAW, 375 PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, 376 PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType() 377 378 Level: beginner 379 M*/ 380 381 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Socket(PetscViewer v) 382 { 383 PetscViewer_Socket *vmatlab; 384 PetscErrorCode ierr; 385 386 PetscFunctionBegin; 387 ierr = PetscNewLog(v,&vmatlab);CHKERRQ(ierr); 388 vmatlab->port = 0; 389 v->data = (void*)vmatlab; 390 v->ops->destroy = PetscViewerDestroy_Socket; 391 v->ops->flush = 0; 392 v->ops->setfromoptions = PetscViewerSetFromOptions_Socket; 393 394 /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */ 395 ierr = PetscObjectChangeTypeName((PetscObject)v,PETSCVIEWERBINARY);CHKERRQ(ierr); 396 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Socket);CHKERRQ(ierr); 397 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Socket);CHKERRQ(ierr); 398 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Socket);CHKERRQ(ierr); 399 400 PetscFunctionReturn(0); 401 } 402 403 /*@C 404 PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket 405 viewer is to use 406 407 Logically Collective on PetscViewer 408 409 Input Parameters: 410 + v - viewer to connect 411 . machine - host to connect to, use NULL for the local machine,use "server" to passively wait for 412 a connection from elsewhere 413 - port - the port on the machine one is connecting to, use PETSC_DEFAULT for default 414 415 Level: advanced 416 417 .seealso: PetscViewerSocketOpen() 418 @*/ 419 PetscErrorCode PetscViewerSocketSetConnection(PetscViewer v,const char machine[],int port) 420 { 421 PetscErrorCode ierr; 422 PetscMPIInt rank; 423 char mach[256]; 424 PetscBool tflg; 425 PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)v->data; 426 427 PetscFunctionBegin; 428 /* PetscValidLogicalCollectiveInt(v,port,3); not a PetscInt */ 429 if (port <= 0) { 430 char portn[16]; 431 ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);CHKERRQ(ierr); 432 if (tflg) { 433 PetscInt pport; 434 ierr = PetscOptionsStringToInt(portn,&pport);CHKERRQ(ierr); 435 port = (int)pport; 436 } else port = PETSCSOCKETDEFAULTPORT; 437 } 438 if (!machine) { 439 ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);CHKERRQ(ierr); 440 if (!tflg) { 441 ierr = PetscGetHostName(mach,256);CHKERRQ(ierr); 442 } 443 } else { 444 ierr = PetscStrncpy(mach,machine,256);CHKERRQ(ierr); 445 } 446 447 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)v),&rank);CHKERRQ(ierr); 448 if (!rank) { 449 ierr = PetscStrcmp(mach,"server",&tflg);CHKERRQ(ierr); 450 if (tflg) { 451 int listenport; 452 ierr = PetscInfo1(v,"Waiting for connection from socket process on port %D\n",port);CHKERRQ(ierr); 453 ierr = PetscSocketEstablish(port,&listenport);CHKERRQ(ierr); 454 ierr = PetscSocketListen(listenport,&vmatlab->port);CHKERRQ(ierr); 455 close(listenport); 456 } else { 457 ierr = PetscInfo2(v,"Connecting to socket process on port %D machine %s\n",port,mach);CHKERRQ(ierr); 458 ierr = PetscOpenSocket(mach,port,&vmatlab->port);CHKERRQ(ierr); 459 } 460 } 461 PetscFunctionReturn(0); 462 } 463 464 /* ---------------------------------------------------------------------*/ 465 /* 466 The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that 467 is attached to a communicator, in this case the attribute is a PetscViewer. 468 */ 469 PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID; 470 471 472 /*@C 473 PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator. 474 475 Collective on MPI_Comm 476 477 Input Parameter: 478 . comm - the MPI communicator to share the socket PetscViewer 479 480 Level: intermediate 481 482 Options Database Keys: 483 For use with the default PETSC_VIEWER_SOCKET_WORLD or if 484 NULL is passed for machine or PETSC_DEFAULT is passed for port 485 $ -viewer_socket_machine <machine> 486 $ -viewer_socket_port <port> 487 488 Environmental variables: 489 + PETSC_VIEWER_SOCKET_PORT portnumber 490 - PETSC_VIEWER_SOCKET_MACHINE machine name 491 492 Notes: 493 Unlike almost all other PETSc routines, PetscViewer_SOCKET_ does not return 494 an error code. The socket PetscViewer is usually used in the form 495 $ XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm)); 496 497 Currently the only socket client available is MATLAB. See 498 src/dm/examples/tests/ex12.c and ex12.m for an example of usage. 499 500 Connects to a waiting socket and stays connected until PetscViewerDestroy() is called. 501 502 Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for writing output to a 503 .mat file. Use PetscMatlabEngineCreate() or PETSC_MATLAB_ENGINE_(), PETSC_MATLAB_ENGINE_SELF, or PETSC_MATLAB_ENGINE_WORLD 504 for communicating with a MATLAB Engine 505 506 .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(), 507 PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(), 508 PetscViewerBinaryWriteStringArray(), PetscViewerBinaryGetDescriptor(), PETSC_VIEWER_MATLAB_() 509 @*/ 510 PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm) 511 { 512 PetscErrorCode ierr; 513 PetscBool flg; 514 PetscViewer viewer; 515 MPI_Comm ncomm; 516 517 PetscFunctionBegin; 518 ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 519 if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) { 520 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0); 521 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 522 } 523 ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_Socket_keyval,(void**)&viewer,(int*)&flg); 524 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 525 if (!flg) { /* PetscViewer not yet created */ 526 ierr = PetscViewerSocketOpen(ncomm,0,0,&viewer); 527 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 528 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 529 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 530 ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_Socket_keyval,(void*)viewer); 531 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 532 } 533 ierr = PetscCommDestroy(&ncomm); 534 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 535 PetscFunctionReturn(viewer); 536 } 537 538