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 Parameter: 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 SETERRQ(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) SETERRQ(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()"); 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; 424 425 PetscFunctionBegin; 426 PetscValidHeaderSpecific(v,PETSC_VIEWER_CLASSID,1); 427 if (machine) PetscValidCharPointer(machine,2); 428 vmatlab = (PetscViewer_Socket*)v->data; 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 == 0) { 450 ierr = PetscStrcmp(mach,"server",&tflg);CHKERRQ(ierr); 451 if (tflg) { 452 int listenport; 453 ierr = PetscInfo(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 = PetscInfo(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 /*@C 473 PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator. 474 475 Collective 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, Petsc_VIEWER_SOCKET_ does not return 494 an error code, it returns NULL if it fails. 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/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(NULL);} 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,NULL); 521 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 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(NULL);} 525 if (!flg) { /* PetscViewer not yet created */ 526 ierr = PetscViewerSocketOpen(ncomm,NULL,0,&viewer); 527 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 528 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 529 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 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(NULL);} 532 } 533 ierr = PetscCommDestroy(&ncomm); 534 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 535 PetscFunctionReturn(viewer); 536 } 537