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 PetscViewer_Socket *vmatlab = (PetscViewer_Socket *)viewer->data; 62 PetscErrorCode ierr; 63 64 PetscFunctionBegin; 65 if (vmatlab->port) { 66 #if defined(PETSC_HAVE_CLOSESOCKET) 67 ierr = closesocket(vmatlab->port); 68 #else 69 ierr = close(vmatlab->port); 70 #endif 71 PetscCheck(!ierr, PETSC_COMM_SELF, PETSC_ERR_SYS, "System error closing socket"); 72 } 73 PetscCall(PetscFree(vmatlab)); 74 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerBinarySetSkipHeader_C", NULL)); 75 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerBinaryGetSkipHeader_C", NULL)); 76 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerBinaryGetFlowControl_C", NULL)); 77 PetscFunctionReturn(0); 78 } 79 80 /*--------------------------------------------------------------*/ 81 /*@C 82 PetscSocketOpen - handles connected to an open port where someone is waiting. 83 84 Input Parameters: 85 + url - for example www.mcs.anl.gov 86 - portnum - for example 80 87 88 Output Parameter: 89 . t - the socket number 90 91 Notes: 92 Use close() to close the socket connection 93 94 Use read() or PetscHTTPRequest() to read from the socket 95 96 Level: advanced 97 98 .seealso: `PetscSocketListen()`, `PetscSocketEstablish()`, `PetscHTTPRequest()`, `PetscHTTPSConnect()` 99 @*/ 100 PetscErrorCode PetscOpenSocket(const char hostname[], int portnum, int *t) { 101 struct sockaddr_in sa; 102 struct hostent *hp; 103 int s = 0; 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 PetscCall(PetscMemzero(&sa, sizeof(sa))); 113 PetscCall(PetscMemcpy(&sa.sin_addr, hp->h_addr_list[0], hp->h_length)); 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"); 120 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SYS, "system error"); 121 } 122 if (connect(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 123 #if defined(PETSC_HAVE_WSAGETLASTERROR) 124 ierr = WSAGetLastError(); 125 if (ierr == WSAEADDRINUSE) (*PetscErrorPrintf)("SEND: address is in use\n"); 126 else if (ierr == WSAEALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n"); 127 else if (ierr == WSAEISCONN) { 128 (*PetscErrorPrintf)("SEND: socket already connected\n"); 129 Sleep((unsigned)1); 130 } else if (ierr == WSAECONNREFUSED) { 131 /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */ 132 Sleep((unsigned)1); 133 } else { 134 perror(NULL); 135 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SYS, "system error"); 136 } 137 #else 138 if (errno == EADDRINUSE) (*PetscErrorPrintf)("SEND: address is in use\n"); 139 else if (errno == EALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n"); 140 else if (errno == EISCONN) { 141 (*PetscErrorPrintf)("SEND: socket already connected\n"); 142 sleep((unsigned)1); 143 } else if (errno == ECONNREFUSED) { 144 refcnt++; 145 PetscCheck(refcnt <= 5, PETSC_COMM_SELF, PETSC_ERR_SYS, "Connection refused by remote host %s port %d", hostname, portnum); 146 PetscCall(PetscInfo(NULL, "Connection refused in attaching socket, trying again\n")); 147 sleep((unsigned)1); 148 } else { 149 perror(NULL); 150 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SYS, "system error"); 151 } 152 #endif 153 flg = PETSC_TRUE; 154 #if defined(PETSC_HAVE_CLOSESOCKET) 155 closesocket(s); 156 #else 157 close(s); 158 #endif 159 } else flg = PETSC_FALSE; 160 } 161 *t = s; 162 PetscFunctionReturn(0); 163 } 164 165 /*@C 166 PetscSocketEstablish - starts a listener on a socket 167 168 Input Parameters: 169 . portnumber - the port to wait at 170 171 Output Parameters: 172 . ss - the socket to be used with PetscSocketListen() 173 174 Level: advanced 175 176 .seealso: `PetscSocketListen()`, `PetscOpenSocket()` 177 178 @*/ 179 PETSC_INTERN PetscErrorCode PetscSocketEstablish(int portnum, int *ss) { 180 static size_t MAXHOSTNAME = 100; 181 char myname[MAXHOSTNAME + 1]; 182 int s; 183 struct sockaddr_in sa; 184 struct hostent *hp; 185 186 PetscFunctionBegin; 187 PetscCall(PetscGetHostName(myname, sizeof(myname))); 188 189 PetscCall(PetscMemzero(&sa, sizeof(struct sockaddr_in))); 190 191 hp = gethostbyname(myname); 192 PetscCheck(hp, 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 PetscCheck((s = socket(AF_INET, SOCK_STREAM, 0)) >= 0, 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 PetscCall(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval))); 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 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 PetscCheck((*t = accept(listenport, (struct sockaddr *)&isa, (socklen_t *)&i)) >= 0, 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 PetscFunctionBegin; 306 PetscCall(PetscViewerCreate(comm, lab)); 307 PetscCall(PetscViewerSetType(*lab, PETSCVIEWERSOCKET)); 308 PetscCall(PetscViewerSocketSetConnection(*lab, machine, port)); 309 PetscFunctionReturn(0); 310 } 311 312 static PetscErrorCode PetscViewerSetFromOptions_Socket(PetscViewer v, PetscOptionItems *PetscOptionsObject) { 313 PetscInt def = -1; 314 char sdef[256]; 315 PetscBool tflg; 316 317 PetscFunctionBegin; 318 /* 319 These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they 320 are listed here for the GUI to display 321 */ 322 PetscOptionsHeadBegin(PetscOptionsObject, "Socket PetscViewer Options"); 323 PetscCall(PetscOptionsGetenv(PetscObjectComm((PetscObject)v), "PETSC_VIEWER_SOCKET_PORT", sdef, 16, &tflg)); 324 if (tflg) { 325 PetscCall(PetscOptionsStringToInt(sdef, &def)); 326 } else def = PETSCSOCKETDEFAULTPORT; 327 PetscCall(PetscOptionsInt("-viewer_socket_port", "Port number to use for socket", "PetscViewerSocketSetConnection", def, NULL, NULL)); 328 329 PetscCall(PetscOptionsString("-viewer_socket_machine", "Machine to use for socket", "PetscViewerSocketSetConnection", sdef, NULL, sizeof(sdef), NULL)); 330 PetscCall(PetscOptionsGetenv(PetscObjectComm((PetscObject)v), "PETSC_VIEWER_SOCKET_MACHINE", sdef, sizeof(sdef), &tflg)); 331 if (!tflg) PetscCall(PetscGetHostName(sdef, sizeof(sdef))); 332 PetscOptionsHeadEnd(); 333 PetscFunctionReturn(0); 334 } 335 336 static PetscErrorCode PetscViewerBinaryGetSkipHeader_Socket(PetscViewer viewer, PetscBool *skip) { 337 PetscViewer_Socket *vsocket = (PetscViewer_Socket *)viewer->data; 338 339 PetscFunctionBegin; 340 *skip = vsocket->skipheader; 341 PetscFunctionReturn(0); 342 } 343 344 static PetscErrorCode PetscViewerBinarySetSkipHeader_Socket(PetscViewer viewer, PetscBool skip) { 345 PetscViewer_Socket *vsocket = (PetscViewer_Socket *)viewer->data; 346 347 PetscFunctionBegin; 348 vsocket->skipheader = skip; 349 PetscFunctionReturn(0); 350 } 351 352 static PetscErrorCode PetscViewerBinaryGetFlowControl_Socket(PetscViewer viewer, PetscInt *fc) { 353 PetscFunctionBegin; 354 *fc = 0; 355 PetscFunctionReturn(0); 356 } 357 358 /*MC 359 PETSCVIEWERSOCKET - A viewer that writes to a Unix socket 360 361 .seealso: `PetscViewerSocketOpen()`, `PetscViewerDrawOpen()`, `PETSC_VIEWER_DRAW_()`, `PETSC_VIEWER_DRAW_SELF`, `PETSC_VIEWER_DRAW_WORLD`, 362 `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`, `PETSCVIEWERDRAW`, 363 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`, 364 `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()` 365 366 Level: beginner 367 M*/ 368 369 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Socket(PetscViewer v) { 370 PetscViewer_Socket *vmatlab; 371 372 PetscFunctionBegin; 373 PetscCall(PetscNewLog(v, &vmatlab)); 374 vmatlab->port = 0; 375 v->data = (void *)vmatlab; 376 v->ops->destroy = PetscViewerDestroy_Socket; 377 v->ops->flush = NULL; 378 v->ops->setfromoptions = PetscViewerSetFromOptions_Socket; 379 380 /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */ 381 PetscCall(PetscObjectChangeTypeName((PetscObject)v, PETSCVIEWERBINARY)); 382 PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipHeader_C", PetscViewerBinarySetSkipHeader_Socket)); 383 PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipHeader_C", PetscViewerBinaryGetSkipHeader_Socket)); 384 PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetFlowControl_C", PetscViewerBinaryGetFlowControl_Socket)); 385 386 PetscFunctionReturn(0); 387 } 388 389 /*@C 390 PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket 391 viewer is to use 392 393 Logically Collective on PetscViewer 394 395 Input Parameters: 396 + v - viewer to connect 397 . machine - host to connect to, use NULL for the local machine,use "server" to passively wait for 398 a connection from elsewhere 399 - port - the port on the machine one is connecting to, use PETSC_DEFAULT for default 400 401 Level: advanced 402 403 .seealso: `PetscViewerSocketOpen()` 404 @*/ 405 PetscErrorCode PetscViewerSocketSetConnection(PetscViewer v, const char machine[], int port) { 406 PetscMPIInt rank; 407 char mach[256]; 408 PetscBool tflg; 409 PetscViewer_Socket *vmatlab; 410 411 PetscFunctionBegin; 412 PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1); 413 if (machine) PetscValidCharPointer(machine, 2); 414 vmatlab = (PetscViewer_Socket *)v->data; 415 /* PetscValidLogicalCollectiveInt(v,port,3); not a PetscInt */ 416 if (port <= 0) { 417 char portn[16]; 418 PetscCall(PetscOptionsGetenv(PetscObjectComm((PetscObject)v), "PETSC_VIEWER_SOCKET_PORT", portn, 16, &tflg)); 419 if (tflg) { 420 PetscInt pport; 421 PetscCall(PetscOptionsStringToInt(portn, &pport)); 422 port = (int)pport; 423 } else port = PETSCSOCKETDEFAULTPORT; 424 } 425 if (!machine) { 426 PetscCall(PetscOptionsGetenv(PetscObjectComm((PetscObject)v), "PETSC_VIEWER_SOCKET_MACHINE", mach, sizeof(mach), &tflg)); 427 if (!tflg) PetscCall(PetscGetHostName(mach, sizeof(mach))); 428 } else { 429 PetscCall(PetscStrncpy(mach, machine, sizeof(mach))); 430 } 431 432 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)v), &rank)); 433 if (rank == 0) { 434 PetscCall(PetscStrcmp(mach, "server", &tflg)); 435 if (tflg) { 436 int listenport; 437 PetscCall(PetscInfo(v, "Waiting for connection from socket process on port %d\n", port)); 438 PetscCall(PetscSocketEstablish(port, &listenport)); 439 PetscCall(PetscSocketListen(listenport, &vmatlab->port)); 440 close(listenport); 441 } else { 442 PetscCall(PetscInfo(v, "Connecting to socket process on port %d machine %s\n", port, mach)); 443 PetscCall(PetscOpenSocket(mach, port, &vmatlab->port)); 444 } 445 } 446 PetscFunctionReturn(0); 447 } 448 449 /* ---------------------------------------------------------------------*/ 450 /* 451 The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that 452 is attached to a communicator, in this case the attribute is a PetscViewer. 453 */ 454 PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID; 455 456 /*@C 457 PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator. 458 459 Collective 460 461 Input Parameter: 462 . comm - the MPI communicator to share the socket PetscViewer 463 464 Level: intermediate 465 466 Options Database Keys: 467 For use with the default PETSC_VIEWER_SOCKET_WORLD or if 468 NULL is passed for machine or PETSC_DEFAULT is passed for port 469 $ -viewer_socket_machine <machine> 470 $ -viewer_socket_port <port> 471 472 Environmental variables: 473 + PETSC_VIEWER_SOCKET_PORT - portnumber 474 - PETSC_VIEWER_SOCKET_MACHINE - machine name 475 476 Notes: 477 Unlike almost all other PETSc routines, Petsc_VIEWER_SOCKET_ does not return 478 an error code, it returns NULL if it fails. The socket PetscViewer is usually used in the form 479 $ XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm)); 480 481 Currently the only socket client available is MATLAB. See 482 src/dm/tests/ex12.c and ex12.m for an example of usage. 483 484 Connects to a waiting socket and stays connected until PetscViewerDestroy() is called. 485 486 Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for writing output to a 487 .mat file. Use PetscMatlabEngineCreate() or PETSC_MATLAB_ENGINE_(), PETSC_MATLAB_ENGINE_SELF, or PETSC_MATLAB_ENGINE_WORLD 488 for communicating with a MATLAB Engine 489 490 .seealso: `PETSC_VIEWER_SOCKET_WORLD`, `PETSC_VIEWER_SOCKET_SELF`, `PetscViewerSocketOpen()`, `PetscViewerCreate()`, 491 `PetscViewerSocketSetConnection()`, `PetscViewerDestroy()`, `PETSC_VIEWER_SOCKET_()`, `PetscViewerBinaryWrite()`, `PetscViewerBinaryRead()`, 492 `PetscViewerBinaryWriteStringArray()`, `PetscViewerBinaryGetDescriptor()`, `PETSC_VIEWER_MATLAB_()` 493 @*/ 494 PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm) { 495 PetscErrorCode ierr; 496 PetscBool flg; 497 PetscViewer viewer; 498 MPI_Comm ncomm; 499 500 PetscFunctionBegin; 501 ierr = PetscCommDuplicate(comm, &ncomm, NULL); 502 if (ierr) { 503 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 504 PetscFunctionReturn(NULL); 505 } 506 if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) { 507 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Socket_keyval, NULL); 508 if (ierr) { 509 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 510 PetscFunctionReturn(NULL); 511 } 512 } 513 ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_Socket_keyval, (void **)&viewer, (int *)&flg); 514 if (ierr) { 515 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 516 PetscFunctionReturn(NULL); 517 } 518 if (!flg) { /* PetscViewer not yet created */ 519 ierr = PetscViewerSocketOpen(ncomm, NULL, 0, &viewer); 520 if (ierr) { 521 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 522 PetscFunctionReturn(NULL); 523 } 524 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 525 if (ierr) { 526 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 527 PetscFunctionReturn(NULL); 528 } 529 ierr = MPI_Comm_set_attr(ncomm, Petsc_Viewer_Socket_keyval, (void *)viewer); 530 if (ierr) { 531 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 532 PetscFunctionReturn(NULL); 533 } 534 } 535 ierr = PetscCommDestroy(&ncomm); 536 if (ierr) { 537 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 538 PetscFunctionReturn(NULL); 539 } 540 PetscFunctionReturn(viewer); 541 } 542