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