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