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