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 #define MAXHOSTNAME 100 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 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,MAXHOSTNAME);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 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,NULL,NULL);CHKERRQ(ierr); 334 335 ierr = PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,NULL,0,NULL);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 = NULL; 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 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/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_INITIAL," ");PetscFunctionReturn(NULL);} 528 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 529 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");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_INITIAL," ");PetscFunctionReturn(NULL);} 535 PetscFunctionReturn(viewer); 536 } 537 538