xref: /petsc/src/sys/classes/viewer/impls/socket/send.c (revision 5c6c1daec53e1d9ab0bec9db5309fd8fc7645b8d)
1*5c6c1daeSBarry Smith 
2*5c6c1daeSBarry Smith #include <petscsys.h>
3*5c6c1daeSBarry Smith 
4*5c6c1daeSBarry Smith #if defined(PETSC_NEEDS_UTYPE_TYPEDEFS)
5*5c6c1daeSBarry Smith /* Some systems have inconsistent include files that use but do not
6*5c6c1daeSBarry Smith    ensure that the following definitions are made */
7*5c6c1daeSBarry Smith typedef unsigned char   u_char;
8*5c6c1daeSBarry Smith typedef unsigned short  u_short;
9*5c6c1daeSBarry Smith typedef unsigned short  ushort;
10*5c6c1daeSBarry Smith typedef unsigned int    u_int;
11*5c6c1daeSBarry Smith typedef unsigned long   u_long;
12*5c6c1daeSBarry Smith #endif
13*5c6c1daeSBarry Smith 
14*5c6c1daeSBarry Smith #include <errno.h>
15*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_STDLIB_H)
16*5c6c1daeSBarry Smith #include <stdlib.h>
17*5c6c1daeSBarry Smith #endif
18*5c6c1daeSBarry Smith #include <sys/types.h>
19*5c6c1daeSBarry Smith #include <ctype.h>
20*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_MACHINE_ENDIAN_H)
21*5c6c1daeSBarry Smith #include <machine/endian.h>
22*5c6c1daeSBarry Smith #endif
23*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_UNISTD_H)
24*5c6c1daeSBarry Smith #include <unistd.h>
25*5c6c1daeSBarry Smith #endif
26*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_SYS_SOCKET_H)
27*5c6c1daeSBarry Smith #include <sys/socket.h>
28*5c6c1daeSBarry Smith #endif
29*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_SYS_WAIT_H)
30*5c6c1daeSBarry Smith #include <sys/wait.h>
31*5c6c1daeSBarry Smith #endif
32*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_NETINET_IN_H)
33*5c6c1daeSBarry Smith #include <netinet/in.h>
34*5c6c1daeSBarry Smith #endif
35*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_NETDB_H)
36*5c6c1daeSBarry Smith #include <netdb.h>
37*5c6c1daeSBarry Smith #endif
38*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_FCNTL_H)
39*5c6c1daeSBarry Smith #include <fcntl.h>
40*5c6c1daeSBarry Smith #endif
41*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_IO_H)
42*5c6c1daeSBarry Smith #include <io.h>
43*5c6c1daeSBarry Smith #endif
44*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_WINSOCK2_H)
45*5c6c1daeSBarry Smith #include <Winsock2.h>
46*5c6c1daeSBarry Smith #endif
47*5c6c1daeSBarry Smith #include <sys/stat.h>
48*5c6c1daeSBarry Smith #include <../src/sys/classes/viewer/impls/socket/socket.h>
49*5c6c1daeSBarry Smith 
50*5c6c1daeSBarry Smith EXTERN_C_BEGIN
51*5c6c1daeSBarry Smith #if defined(PETSC_NEED_CLOSE_PROTO)
52*5c6c1daeSBarry Smith extern int close(int);
53*5c6c1daeSBarry Smith #endif
54*5c6c1daeSBarry Smith #if defined(PETSC_NEED_SOCKET_PROTO)
55*5c6c1daeSBarry Smith extern int socket(int,int,int);
56*5c6c1daeSBarry Smith #endif
57*5c6c1daeSBarry Smith #if defined(PETSC_NEED_SLEEP_PROTO)
58*5c6c1daeSBarry Smith extern int sleep(unsigned);
59*5c6c1daeSBarry Smith #endif
60*5c6c1daeSBarry Smith #if defined(PETSC_NEED_CONNECT_PROTO)
61*5c6c1daeSBarry Smith extern int connect(int,struct sockaddr *,int);
62*5c6c1daeSBarry Smith #endif
63*5c6c1daeSBarry Smith EXTERN_C_END
64*5c6c1daeSBarry Smith 
65*5c6c1daeSBarry Smith /*--------------------------------------------------------------*/
66*5c6c1daeSBarry Smith #undef __FUNCT__
67*5c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerDestroy_Socket"
68*5c6c1daeSBarry Smith static PetscErrorCode PetscViewerDestroy_Socket(PetscViewer viewer)
69*5c6c1daeSBarry Smith {
70*5c6c1daeSBarry Smith   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data;
71*5c6c1daeSBarry Smith   PetscErrorCode     ierr;
72*5c6c1daeSBarry Smith 
73*5c6c1daeSBarry Smith   PetscFunctionBegin;
74*5c6c1daeSBarry Smith   if (vmatlab->port) {
75*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_CLOSESOCKET)
76*5c6c1daeSBarry Smith     ierr = closesocket(vmatlab->port);
77*5c6c1daeSBarry Smith #else
78*5c6c1daeSBarry Smith     ierr = close(vmatlab->port);
79*5c6c1daeSBarry Smith #endif
80*5c6c1daeSBarry Smith     if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"System error closing socket");
81*5c6c1daeSBarry Smith   }
82*5c6c1daeSBarry Smith   ierr = PetscFree(vmatlab);CHKERRQ(ierr);
83*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
84*5c6c1daeSBarry Smith }
85*5c6c1daeSBarry Smith 
86*5c6c1daeSBarry Smith /*--------------------------------------------------------------*/
87*5c6c1daeSBarry Smith #undef __FUNCT__
88*5c6c1daeSBarry Smith #define __FUNCT__ "PetscOpenSocket"
89*5c6c1daeSBarry Smith /*
90*5c6c1daeSBarry Smith     PetscSocketOpen - handles connected to an open port where someone is waiting.
91*5c6c1daeSBarry Smith 
92*5c6c1daeSBarry Smith .seealso:   PetscSocketListen(), PetscSocketEstablish()
93*5c6c1daeSBarry Smith */
94*5c6c1daeSBarry Smith PetscErrorCode  PetscOpenSocket(char *hostname,int portnum,int *t)
95*5c6c1daeSBarry Smith {
96*5c6c1daeSBarry Smith   struct sockaddr_in sa;
97*5c6c1daeSBarry Smith   struct hostent     *hp;
98*5c6c1daeSBarry Smith   int                s = 0;
99*5c6c1daeSBarry Smith   PetscErrorCode     ierr;
100*5c6c1daeSBarry Smith   PetscBool          flg = PETSC_TRUE;
101*5c6c1daeSBarry Smith 
102*5c6c1daeSBarry Smith   PetscFunctionBegin;
103*5c6c1daeSBarry Smith   if (!(hp=gethostbyname(hostname))) {
104*5c6c1daeSBarry Smith     perror("SEND: error gethostbyname: ");
105*5c6c1daeSBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error open connection to %s",hostname);
106*5c6c1daeSBarry Smith   }
107*5c6c1daeSBarry Smith   ierr = PetscMemzero(&sa,sizeof(sa));CHKERRQ(ierr);
108*5c6c1daeSBarry Smith   ierr = PetscMemcpy(&sa.sin_addr,hp->h_addr_list[0],hp->h_length);CHKERRQ(ierr);
109*5c6c1daeSBarry Smith 
110*5c6c1daeSBarry Smith   sa.sin_family = hp->h_addrtype;
111*5c6c1daeSBarry Smith   sa.sin_port = htons((u_short) portnum);
112*5c6c1daeSBarry Smith   while (flg) {
113*5c6c1daeSBarry Smith     if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) {
114*5c6c1daeSBarry Smith       perror("SEND: error socket");  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
115*5c6c1daeSBarry Smith     }
116*5c6c1daeSBarry Smith     if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
117*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_WSAGETLASTERROR)
118*5c6c1daeSBarry Smith       ierr = WSAGetLastError();
119*5c6c1daeSBarry Smith       if (ierr == WSAEADDRINUSE) {
120*5c6c1daeSBarry Smith         (*PetscErrorPrintf)("SEND: address is in use\n");
121*5c6c1daeSBarry Smith       } else if (ierr == WSAEALREADY) {
122*5c6c1daeSBarry Smith         (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
123*5c6c1daeSBarry Smith       } else if (ierr == WSAEISCONN) {
124*5c6c1daeSBarry Smith         (*PetscErrorPrintf)("SEND: socket already connected\n");
125*5c6c1daeSBarry Smith         Sleep((unsigned) 1);
126*5c6c1daeSBarry Smith       } else if (ierr == WSAECONNREFUSED) {
127*5c6c1daeSBarry Smith         /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */
128*5c6c1daeSBarry Smith         Sleep((unsigned) 1);
129*5c6c1daeSBarry Smith       } else {
130*5c6c1daeSBarry Smith         perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
131*5c6c1daeSBarry Smith       }
132*5c6c1daeSBarry Smith #else
133*5c6c1daeSBarry Smith       if (errno == EADDRINUSE) {
134*5c6c1daeSBarry Smith         (*PetscErrorPrintf)("SEND: address is in use\n");
135*5c6c1daeSBarry Smith       } else if (errno == EALREADY) {
136*5c6c1daeSBarry Smith         (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
137*5c6c1daeSBarry Smith       } else if (errno == EISCONN) {
138*5c6c1daeSBarry Smith         (*PetscErrorPrintf)("SEND: socket already connected\n");
139*5c6c1daeSBarry Smith         sleep((unsigned) 1);
140*5c6c1daeSBarry Smith       } else if (errno == ECONNREFUSED) {
141*5c6c1daeSBarry Smith         /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */
142*5c6c1daeSBarry Smith         ierr = PetscInfo(0,"Connection refused in attaching socket, trying again");CHKERRQ(ierr);
143*5c6c1daeSBarry Smith         sleep((unsigned) 1);
144*5c6c1daeSBarry Smith       } else {
145*5c6c1daeSBarry Smith         perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
146*5c6c1daeSBarry Smith       }
147*5c6c1daeSBarry Smith #endif
148*5c6c1daeSBarry Smith       flg = PETSC_TRUE;
149*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_CLOSESOCKET)
150*5c6c1daeSBarry Smith       closesocket(s);
151*5c6c1daeSBarry Smith #else
152*5c6c1daeSBarry Smith       close(s);
153*5c6c1daeSBarry Smith #endif
154*5c6c1daeSBarry Smith     }
155*5c6c1daeSBarry Smith     else flg = PETSC_FALSE;
156*5c6c1daeSBarry Smith   }
157*5c6c1daeSBarry Smith   *t = s;
158*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
159*5c6c1daeSBarry Smith }
160*5c6c1daeSBarry Smith 
161*5c6c1daeSBarry Smith #define MAXHOSTNAME 100
162*5c6c1daeSBarry Smith #undef __FUNCT__
163*5c6c1daeSBarry Smith #define __FUNCT__ "PetscSocketEstablish"
164*5c6c1daeSBarry Smith /*
165*5c6c1daeSBarry Smith    PetscSocketEstablish - starts a listener on a socket
166*5c6c1daeSBarry Smith 
167*5c6c1daeSBarry Smith .seealso:   PetscSocketListen()
168*5c6c1daeSBarry Smith */
169*5c6c1daeSBarry Smith PetscErrorCode PetscSocketEstablish(int portnum,int *ss)
170*5c6c1daeSBarry Smith {
171*5c6c1daeSBarry Smith   char               myname[MAXHOSTNAME+1];
172*5c6c1daeSBarry Smith   int                s;
173*5c6c1daeSBarry Smith   PetscErrorCode     ierr;
174*5c6c1daeSBarry Smith   struct sockaddr_in sa;
175*5c6c1daeSBarry Smith   struct hostent     *hp;
176*5c6c1daeSBarry Smith 
177*5c6c1daeSBarry Smith   PetscFunctionBegin;
178*5c6c1daeSBarry Smith   ierr = PetscGetHostName(myname,MAXHOSTNAME);CHKERRQ(ierr);
179*5c6c1daeSBarry Smith 
180*5c6c1daeSBarry Smith   ierr = PetscMemzero(&sa,sizeof(struct sockaddr_in));CHKERRQ(ierr);
181*5c6c1daeSBarry Smith 
182*5c6c1daeSBarry Smith   hp = gethostbyname(myname);
183*5c6c1daeSBarry Smith   if (!hp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Unable to get hostent information from system");
184*5c6c1daeSBarry Smith 
185*5c6c1daeSBarry Smith   sa.sin_family = hp->h_addrtype;
186*5c6c1daeSBarry Smith   sa.sin_port = htons((u_short)portnum);
187*5c6c1daeSBarry Smith 
188*5c6c1daeSBarry Smith   if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error running socket() command");
189*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_SO_REUSEADDR)
190*5c6c1daeSBarry Smith   {
191*5c6c1daeSBarry Smith     int optval = 1; /* Turn on the option */
192*5c6c1daeSBarry Smith     ierr = setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&optval,sizeof(optval));CHKERRQ(ierr);
193*5c6c1daeSBarry Smith   }
194*5c6c1daeSBarry Smith #endif
195*5c6c1daeSBarry Smith 
196*5c6c1daeSBarry Smith   while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
197*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_WSAGETLASTERROR)
198*5c6c1daeSBarry Smith     ierr = WSAGetLastError();
199*5c6c1daeSBarry Smith     if (ierr != WSAEADDRINUSE) {
200*5c6c1daeSBarry Smith #else
201*5c6c1daeSBarry Smith     if (errno != EADDRINUSE) {
202*5c6c1daeSBarry Smith #endif
203*5c6c1daeSBarry Smith       close(s);
204*5c6c1daeSBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error from bind()");
205*5c6c1daeSBarry Smith     }
206*5c6c1daeSBarry Smith   }
207*5c6c1daeSBarry Smith   listen(s,0);
208*5c6c1daeSBarry Smith   *ss = s;
209*5c6c1daeSBarry Smith   return(0);
210*5c6c1daeSBarry Smith }
211*5c6c1daeSBarry Smith 
212*5c6c1daeSBarry Smith #undef __FUNCT__
213*5c6c1daeSBarry Smith #define __FUNCT__ "PetscSocketListen"
214*5c6c1daeSBarry Smith /*
215*5c6c1daeSBarry Smith    PetscSocketListens - Listens at a socket created with PetscSocketEstablish()
216*5c6c1daeSBarry Smith 
217*5c6c1daeSBarry Smith .seealso:   PetscSocketEstablish()
218*5c6c1daeSBarry Smith */
219*5c6c1daeSBarry Smith PetscErrorCode PetscSocketListen(int listenport,int *t)
220*5c6c1daeSBarry Smith {
221*5c6c1daeSBarry Smith   struct sockaddr_in isa;
222*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
223*5c6c1daeSBarry Smith   size_t             i;
224*5c6c1daeSBarry Smith #else
225*5c6c1daeSBarry Smith   int                i;
226*5c6c1daeSBarry Smith #endif
227*5c6c1daeSBarry Smith 
228*5c6c1daeSBarry Smith   PetscFunctionBegin;
229*5c6c1daeSBarry Smith   /* wait for someone to try to connect */
230*5c6c1daeSBarry Smith   i = sizeof(struct sockaddr_in);
231*5c6c1daeSBarry Smith   if ((*t = accept(listenport,(struct sockaddr *)&isa,(socklen_t *)&i)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"error from accept()\n");
232*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
233*5c6c1daeSBarry Smith }
234*5c6c1daeSBarry Smith 
235*5c6c1daeSBarry Smith #undef __FUNCT__
236*5c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerSocketOpen"
237*5c6c1daeSBarry Smith /*@C
238*5c6c1daeSBarry Smith    PetscViewerSocketOpen - Opens a connection to a MATLAB or other socket
239*5c6c1daeSBarry Smith         based server.
240*5c6c1daeSBarry Smith 
241*5c6c1daeSBarry Smith    Collective on MPI_Comm
242*5c6c1daeSBarry Smith 
243*5c6c1daeSBarry Smith    Input Parameters:
244*5c6c1daeSBarry Smith +  comm - the MPI communicator
245*5c6c1daeSBarry Smith .  machine - the machine the server is running on,, use PETSC_NULL for the local machine, use "server" to passively wait for
246*5c6c1daeSBarry Smith              a connection from elsewhere
247*5c6c1daeSBarry Smith -  port - the port to connect to, use PETSC_DEFAULT for the default
248*5c6c1daeSBarry Smith 
249*5c6c1daeSBarry Smith    Output Parameter:
250*5c6c1daeSBarry Smith .  lab - a context to use when communicating with the server
251*5c6c1daeSBarry Smith 
252*5c6c1daeSBarry Smith    Level: intermediate
253*5c6c1daeSBarry Smith 
254*5c6c1daeSBarry Smith    Notes:
255*5c6c1daeSBarry Smith    Most users should employ the following commands to access the
256*5c6c1daeSBarry Smith    MATLAB PetscViewers
257*5c6c1daeSBarry Smith $
258*5c6c1daeSBarry Smith $    PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
259*5c6c1daeSBarry Smith $    MatView(Mat matrix,PetscViewer viewer)
260*5c6c1daeSBarry Smith $
261*5c6c1daeSBarry Smith $                or
262*5c6c1daeSBarry Smith $
263*5c6c1daeSBarry Smith $    PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
264*5c6c1daeSBarry Smith $    VecView(Vec vector,PetscViewer viewer)
265*5c6c1daeSBarry Smith 
266*5c6c1daeSBarry Smith    Options Database Keys:
267*5c6c1daeSBarry Smith    For use with  PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
268*5c6c1daeSBarry Smith    PETSC_VIEWER_SOCKET_() or if
269*5c6c1daeSBarry Smith     PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
270*5c6c1daeSBarry Smith $    -viewer_socket_machine <machine>
271*5c6c1daeSBarry Smith $    -viewer_socket_port <port>
272*5c6c1daeSBarry Smith 
273*5c6c1daeSBarry Smith    Environmental variables:
274*5c6c1daeSBarry Smith +   PETSC_VIEWER_SOCKET_PORT portnumber
275*5c6c1daeSBarry Smith -   PETSC_VIEWER_SOCKET_MACHINE machine name
276*5c6c1daeSBarry Smith 
277*5c6c1daeSBarry Smith      Currently the only socket client available is MATLAB. See
278*5c6c1daeSBarry Smith      src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.
279*5c6c1daeSBarry Smith 
280*5c6c1daeSBarry Smith    Notes: The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket
281*5c6c1daeSBarry Smith           use PetscViewerBinaryRead/Write/GetDescriptor().
282*5c6c1daeSBarry Smith 
283*5c6c1daeSBarry Smith    Concepts: MATLAB^sending data
284*5c6c1daeSBarry Smith    Concepts: sockets^sending data
285*5c6c1daeSBarry Smith 
286*5c6c1daeSBarry Smith .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
287*5c6c1daeSBarry Smith           PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD,
288*5c6c1daeSBarry Smith           PETSC_VIEWER_SOCKET_SELF, PetscViewerBinaryWrite(), PetscViewerBinaryRead(), PetscViewerBinaryWriteStringArray(),
289*5c6c1daeSBarry Smith           PetscBinaryViewerGetDescriptor()
290*5c6c1daeSBarry Smith @*/
291*5c6c1daeSBarry Smith PetscErrorCode  PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
292*5c6c1daeSBarry Smith {
293*5c6c1daeSBarry Smith   PetscErrorCode ierr;
294*5c6c1daeSBarry Smith 
295*5c6c1daeSBarry Smith   PetscFunctionBegin;
296*5c6c1daeSBarry Smith   ierr = PetscViewerCreate(comm,lab);CHKERRQ(ierr);
297*5c6c1daeSBarry Smith   ierr = PetscViewerSetType(*lab,PETSCVIEWERSOCKET);CHKERRQ(ierr);
298*5c6c1daeSBarry Smith   ierr = PetscViewerSocketSetConnection(*lab,machine,port);CHKERRQ(ierr);
299*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
300*5c6c1daeSBarry Smith }
301*5c6c1daeSBarry Smith 
302*5c6c1daeSBarry Smith #undef __FUNCT__
303*5c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerSetFromOptions_Socket"
304*5c6c1daeSBarry Smith PetscErrorCode PetscViewerSetFromOptions_Socket(PetscViewer v)
305*5c6c1daeSBarry Smith {
306*5c6c1daeSBarry Smith   PetscErrorCode ierr;
307*5c6c1daeSBarry Smith   PetscInt       def = -1;
308*5c6c1daeSBarry Smith   char           sdef[256];
309*5c6c1daeSBarry Smith   PetscBool      tflg;
310*5c6c1daeSBarry Smith 
311*5c6c1daeSBarry Smith   PetscFunctionBegin;
312*5c6c1daeSBarry Smith   /*
313*5c6c1daeSBarry Smith        These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
314*5c6c1daeSBarry Smith     are listed here for the GUI to display
315*5c6c1daeSBarry Smith   */
316*5c6c1daeSBarry Smith   ierr = PetscOptionsHead("Socket PetscViewer Options");CHKERRQ(ierr);
317*5c6c1daeSBarry Smith     ierr = PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);CHKERRQ(ierr);
318*5c6c1daeSBarry Smith     if (tflg) {
319*5c6c1daeSBarry Smith       ierr = PetscOptionsStringToInt(sdef,&def);CHKERRQ(ierr);
320*5c6c1daeSBarry Smith     } else {
321*5c6c1daeSBarry Smith       def = PETSCSOCKETDEFAULTPORT;
322*5c6c1daeSBarry Smith     }
323*5c6c1daeSBarry Smith     ierr = PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);CHKERRQ(ierr);
324*5c6c1daeSBarry Smith 
325*5c6c1daeSBarry Smith     ierr = PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);CHKERRQ(ierr);
326*5c6c1daeSBarry Smith     ierr = PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);CHKERRQ(ierr);
327*5c6c1daeSBarry Smith     if (!tflg) {
328*5c6c1daeSBarry Smith       ierr = PetscGetHostName(sdef,256);CHKERRQ(ierr);
329*5c6c1daeSBarry Smith     }
330*5c6c1daeSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
331*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
332*5c6c1daeSBarry Smith }
333*5c6c1daeSBarry Smith 
334*5c6c1daeSBarry Smith EXTERN_C_BEGIN
335*5c6c1daeSBarry Smith #undef __FUNCT__
336*5c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerCreate_Socket"
337*5c6c1daeSBarry Smith PetscErrorCode  PetscViewerCreate_Socket(PetscViewer v)
338*5c6c1daeSBarry Smith {
339*5c6c1daeSBarry Smith   PetscViewer_Socket *vmatlab;
340*5c6c1daeSBarry Smith   PetscErrorCode     ierr;
341*5c6c1daeSBarry Smith 
342*5c6c1daeSBarry Smith   PetscFunctionBegin;
343*5c6c1daeSBarry Smith   ierr                   = PetscNewLog(v,PetscViewer_Socket,&vmatlab);CHKERRQ(ierr);
344*5c6c1daeSBarry Smith   vmatlab->port          = 0;
345*5c6c1daeSBarry Smith   v->data                = (void*)vmatlab;
346*5c6c1daeSBarry Smith   v->ops->destroy        = PetscViewerDestroy_Socket;
347*5c6c1daeSBarry Smith   v->ops->flush          = 0;
348*5c6c1daeSBarry Smith   v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;
349*5c6c1daeSBarry Smith 
350*5c6c1daeSBarry Smith   /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */
351*5c6c1daeSBarry Smith   ierr                   = PetscObjectChangeTypeName((PetscObject)v,PETSCVIEWERBINARY);CHKERRQ(ierr);
352*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
353*5c6c1daeSBarry Smith }
354*5c6c1daeSBarry Smith EXTERN_C_END
355*5c6c1daeSBarry Smith 
356*5c6c1daeSBarry Smith #undef __FUNCT__
357*5c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerSocketSetConnection"
358*5c6c1daeSBarry Smith /*@C
359*5c6c1daeSBarry Smith       PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket
360*5c6c1daeSBarry Smith              viewer is to use
361*5c6c1daeSBarry Smith 
362*5c6c1daeSBarry Smith   Logically Collective on PetscViewer
363*5c6c1daeSBarry Smith 
364*5c6c1daeSBarry Smith   Input Parameters:
365*5c6c1daeSBarry Smith +   v - viewer to connect
366*5c6c1daeSBarry Smith .   machine - host to connect to, use PETSC_NULL for the local machine,use "server" to passively wait for
367*5c6c1daeSBarry Smith              a connection from elsewhere
368*5c6c1daeSBarry Smith -   port - the port on the machine one is connecting to, use PETSC_DEFAULT for default
369*5c6c1daeSBarry Smith 
370*5c6c1daeSBarry Smith     Level: advanced
371*5c6c1daeSBarry Smith 
372*5c6c1daeSBarry Smith .seealso: PetscViewerSocketOpen()
373*5c6c1daeSBarry Smith @*/
374*5c6c1daeSBarry Smith PetscErrorCode  PetscViewerSocketSetConnection(PetscViewer v,const char machine[],int port)
375*5c6c1daeSBarry Smith {
376*5c6c1daeSBarry Smith   PetscErrorCode     ierr;
377*5c6c1daeSBarry Smith   PetscMPIInt        rank;
378*5c6c1daeSBarry Smith   char               mach[256];
379*5c6c1daeSBarry Smith   PetscBool          tflg;
380*5c6c1daeSBarry Smith   PetscViewer_Socket *vmatlab = (PetscViewer_Socket *)v->data;
381*5c6c1daeSBarry Smith 
382*5c6c1daeSBarry Smith   PetscFunctionBegin;
383*5c6c1daeSBarry Smith   /* PetscValidLogicalCollectiveInt(v,port,3); not a PetscInt */
384*5c6c1daeSBarry Smith   if (port <= 0) {
385*5c6c1daeSBarry Smith     char portn[16];
386*5c6c1daeSBarry Smith     ierr = PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);CHKERRQ(ierr);
387*5c6c1daeSBarry Smith     if (tflg) {
388*5c6c1daeSBarry Smith       PetscInt pport;
389*5c6c1daeSBarry Smith       ierr = PetscOptionsStringToInt(portn,&pport);CHKERRQ(ierr);
390*5c6c1daeSBarry Smith       port = (int)pport;
391*5c6c1daeSBarry Smith     } else {
392*5c6c1daeSBarry Smith       port = PETSCSOCKETDEFAULTPORT;
393*5c6c1daeSBarry Smith     }
394*5c6c1daeSBarry Smith   }
395*5c6c1daeSBarry Smith   if (!machine) {
396*5c6c1daeSBarry Smith     ierr = PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);CHKERRQ(ierr);
397*5c6c1daeSBarry Smith     if (!tflg) {
398*5c6c1daeSBarry Smith       ierr = PetscGetHostName(mach,256);CHKERRQ(ierr);
399*5c6c1daeSBarry Smith     }
400*5c6c1daeSBarry Smith   } else {
401*5c6c1daeSBarry Smith     ierr = PetscStrncpy(mach,machine,256);CHKERRQ(ierr);
402*5c6c1daeSBarry Smith   }
403*5c6c1daeSBarry Smith 
404*5c6c1daeSBarry Smith   ierr = MPI_Comm_rank(((PetscObject)v)->comm,&rank);CHKERRQ(ierr);
405*5c6c1daeSBarry Smith   if (!rank) {
406*5c6c1daeSBarry Smith     ierr = PetscStrcmp(mach,"server",&tflg);CHKERRQ(ierr);
407*5c6c1daeSBarry Smith     if (tflg) {
408*5c6c1daeSBarry Smith       int listenport;
409*5c6c1daeSBarry Smith       ierr = PetscInfo1(v,"Waiting for connection from socket process on port %D\n",port);CHKERRQ(ierr);
410*5c6c1daeSBarry Smith       ierr = PetscSocketEstablish(port,&listenport);CHKERRQ(ierr);
411*5c6c1daeSBarry Smith       ierr = PetscSocketListen(listenport,&vmatlab->port);CHKERRQ(ierr);
412*5c6c1daeSBarry Smith       close(listenport);
413*5c6c1daeSBarry Smith     } else {
414*5c6c1daeSBarry Smith       ierr = PetscInfo2(v,"Connecting to socket process on port %D machine %s\n",port,mach);CHKERRQ(ierr);
415*5c6c1daeSBarry Smith       ierr = PetscOpenSocket(mach,port,&vmatlab->port);CHKERRQ(ierr);
416*5c6c1daeSBarry Smith     }
417*5c6c1daeSBarry Smith   }
418*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
419*5c6c1daeSBarry Smith }
420*5c6c1daeSBarry Smith 
421*5c6c1daeSBarry Smith /* ---------------------------------------------------------------------*/
422*5c6c1daeSBarry Smith /*
423*5c6c1daeSBarry Smith     The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
424*5c6c1daeSBarry Smith   is attached to a communicator, in this case the attribute is a PetscViewer.
425*5c6c1daeSBarry Smith */
426*5c6c1daeSBarry Smith static PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;
427*5c6c1daeSBarry Smith 
428*5c6c1daeSBarry Smith 
429*5c6c1daeSBarry Smith #undef __FUNCT__
430*5c6c1daeSBarry Smith #define __FUNCT__ "PETSC_VIEWER_SOCKET_"
431*5c6c1daeSBarry Smith /*@C
432*5c6c1daeSBarry Smith      PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator.
433*5c6c1daeSBarry Smith 
434*5c6c1daeSBarry Smith      Collective on MPI_Comm
435*5c6c1daeSBarry Smith 
436*5c6c1daeSBarry Smith      Input Parameter:
437*5c6c1daeSBarry Smith .    comm - the MPI communicator to share the socket PetscViewer
438*5c6c1daeSBarry Smith 
439*5c6c1daeSBarry Smith      Level: intermediate
440*5c6c1daeSBarry Smith 
441*5c6c1daeSBarry Smith    Options Database Keys:
442*5c6c1daeSBarry Smith    For use with the default PETSC_VIEWER_SOCKET_WORLD or if
443*5c6c1daeSBarry Smith     PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
444*5c6c1daeSBarry Smith $    -viewer_socket_machine <machine>
445*5c6c1daeSBarry Smith $    -viewer_socket_port <port>
446*5c6c1daeSBarry Smith 
447*5c6c1daeSBarry Smith    Environmental variables:
448*5c6c1daeSBarry Smith +   PETSC_VIEWER_SOCKET_PORT portnumber
449*5c6c1daeSBarry Smith -   PETSC_VIEWER_SOCKET_MACHINE machine name
450*5c6c1daeSBarry Smith 
451*5c6c1daeSBarry Smith      Notes:
452*5c6c1daeSBarry Smith      Unlike almost all other PETSc routines, PetscViewer_SOCKET_ does not return
453*5c6c1daeSBarry Smith      an error code.  The socket PetscViewer is usually used in the form
454*5c6c1daeSBarry Smith $       XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm));
455*5c6c1daeSBarry Smith 
456*5c6c1daeSBarry Smith      Currently the only socket client available is MATLAB. See
457*5c6c1daeSBarry Smith      src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.
458*5c6c1daeSBarry Smith 
459*5c6c1daeSBarry Smith      Connects to a waiting socket and stays connected until PetscViewerDestroy() is called.
460*5c6c1daeSBarry Smith 
461*5c6c1daeSBarry Smith      Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for communicating with the MATLAB engine.
462*5c6c1daeSBarry Smith 
463*5c6c1daeSBarry Smith .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
464*5c6c1daeSBarry Smith           PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(),
465*5c6c1daeSBarry Smith           PetscViewerBinaryWriteStringArray(), PetscBinaryViewerGetDescriptor(), PETSC_VIEWER_MATLAB_()
466*5c6c1daeSBarry Smith @*/
467*5c6c1daeSBarry Smith PetscViewer  PETSC_VIEWER_SOCKET_(MPI_Comm comm)
468*5c6c1daeSBarry Smith {
469*5c6c1daeSBarry Smith   PetscErrorCode ierr;
470*5c6c1daeSBarry Smith   PetscBool      flg;
471*5c6c1daeSBarry Smith   PetscViewer    viewer;
472*5c6c1daeSBarry Smith   MPI_Comm       ncomm;
473*5c6c1daeSBarry Smith 
474*5c6c1daeSBarry Smith   PetscFunctionBegin;
475*5c6c1daeSBarry Smith   ierr = PetscCommDuplicate(comm,&ncomm,PETSC_NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
476*5c6c1daeSBarry Smith   if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) {
477*5c6c1daeSBarry Smith     ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0);
478*5c6c1daeSBarry Smith     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
479*5c6c1daeSBarry Smith   }
480*5c6c1daeSBarry Smith   ierr = MPI_Attr_get(ncomm,Petsc_Viewer_Socket_keyval,(void **)&viewer,(int*)&flg);
481*5c6c1daeSBarry Smith   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
482*5c6c1daeSBarry Smith   if (!flg) { /* PetscViewer not yet created */
483*5c6c1daeSBarry Smith     ierr = PetscViewerSocketOpen(ncomm,0,0,&viewer);
484*5c6c1daeSBarry Smith     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
485*5c6c1daeSBarry Smith     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
486*5c6c1daeSBarry Smith     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
487*5c6c1daeSBarry Smith     ierr = MPI_Attr_put(ncomm,Petsc_Viewer_Socket_keyval,(void*)viewer);
488*5c6c1daeSBarry Smith     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
489*5c6c1daeSBarry Smith   }
490*5c6c1daeSBarry Smith   ierr = PetscCommDestroy(&ncomm);
491*5c6c1daeSBarry Smith   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
492*5c6c1daeSBarry Smith   PetscFunctionReturn(viewer);
493*5c6c1daeSBarry Smith }
494*5c6c1daeSBarry Smith 
495*5c6c1daeSBarry Smith #if defined(PETSC_USE_SERVER)
496*5c6c1daeSBarry Smith 
497*5c6c1daeSBarry Smith #include <pthread.h>
498*5c6c1daeSBarry Smith #include <time.h>
499*5c6c1daeSBarry Smith #define PROTOCOL   "HTTP/1.1"
500*5c6c1daeSBarry Smith #define RFC1123FMT "%a, %d %b %Y %H:%M:%S GMT"
501*5c6c1daeSBarry Smith 
502*5c6c1daeSBarry Smith #undef __FUNCT__
503*5c6c1daeSBarry Smith #define __FUNCT__ "PetscWebSendHeader"
504*5c6c1daeSBarry Smith PetscErrorCode PetscWebSendHeader(FILE *f, int status, const char *title, const char *extra, const char *mime, int length)
505*5c6c1daeSBarry Smith {
506*5c6c1daeSBarry Smith   time_t now;
507*5c6c1daeSBarry Smith   char   timebuf[128];
508*5c6c1daeSBarry Smith 
509*5c6c1daeSBarry Smith   PetscFunctionBegin;
510*5c6c1daeSBarry Smith   fprintf(f, "%s %d %s\r\n", PROTOCOL, status, title);
511*5c6c1daeSBarry Smith   fprintf(f, "Server: %s\r\n", "petscserver/1.0");
512*5c6c1daeSBarry Smith   now = time(NULL);
513*5c6c1daeSBarry Smith   strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&now));
514*5c6c1daeSBarry Smith   fprintf(f, "Date: %s\r\n", timebuf);
515*5c6c1daeSBarry Smith   if (extra) fprintf(f, "%s\r\n", extra);
516*5c6c1daeSBarry Smith   if (mime) fprintf(f, "Content-Type: %s\r\n", mime);
517*5c6c1daeSBarry Smith   if (length >= 0) fprintf(f, "Content-Length: %d\r\n", length);
518*5c6c1daeSBarry Smith   fprintf(f, "Connection: close\r\n");
519*5c6c1daeSBarry Smith   fprintf(f, "\r\n");
520*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
521*5c6c1daeSBarry Smith }
522*5c6c1daeSBarry Smith 
523*5c6c1daeSBarry Smith #undef __FUNCT__
524*5c6c1daeSBarry Smith #define __FUNCT__ "PetscWebSendFooter"
525*5c6c1daeSBarry Smith PetscErrorCode PetscWebSendFooter(FILE *fd)
526*5c6c1daeSBarry Smith {
527*5c6c1daeSBarry Smith   PetscFunctionBegin;
528*5c6c1daeSBarry Smith   fprintf(fd, "</BODY></HTML>\r\n");
529*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
530*5c6c1daeSBarry Smith }
531*5c6c1daeSBarry Smith 
532*5c6c1daeSBarry Smith #undef __FUNCT__
533*5c6c1daeSBarry Smith #define __FUNCT__ "PetscWebSendError"
534*5c6c1daeSBarry Smith PetscErrorCode PetscWebSendError(FILE *f, int status, const char *title, const char *extra, const char *text)
535*5c6c1daeSBarry Smith {
536*5c6c1daeSBarry Smith   PetscErrorCode ierr;
537*5c6c1daeSBarry Smith 
538*5c6c1daeSBarry Smith   PetscFunctionBegin;
539*5c6c1daeSBarry Smith   ierr = PetscWebSendHeader(f, status, title, extra, "text/html", -1);CHKERRQ(ierr);
540*5c6c1daeSBarry Smith   fprintf(f, "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\r\n", status, title);
541*5c6c1daeSBarry Smith   fprintf(f, "<BODY><H4>%d %s</H4>\r\n", status, title);
542*5c6c1daeSBarry Smith   fprintf(f, "%s\r\n", text);
543*5c6c1daeSBarry Smith   ierr = PetscWebSendFooter(f);CHKERRQ(ierr);
544*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
545*5c6c1daeSBarry Smith }
546*5c6c1daeSBarry Smith 
547*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_AMS)
548*5c6c1daeSBarry Smith #undef __FUNCT__
549*5c6c1daeSBarry Smith #define __FUNCT__ "PetscAMSDisplayList"
550*5c6c1daeSBarry Smith PetscErrorCode PetscAMSDisplayList(FILE *fd)
551*5c6c1daeSBarry Smith {
552*5c6c1daeSBarry Smith   PetscErrorCode     ierr;
553*5c6c1daeSBarry Smith   char               host[256],**comm_list,**mem_list,**fld_list;
554*5c6c1daeSBarry Smith   AMS_Comm           ams;
555*5c6c1daeSBarry Smith   PetscInt           i = 0,j;
556*5c6c1daeSBarry Smith   AMS_Memory_type    mtype;
557*5c6c1daeSBarry Smith   AMS_Data_type      dtype;
558*5c6c1daeSBarry Smith   AMS_Shared_type    stype;
559*5c6c1daeSBarry Smith   AMS_Reduction_type rtype;
560*5c6c1daeSBarry Smith   AMS_Memory         memory;
561*5c6c1daeSBarry Smith   int                len;
562*5c6c1daeSBarry Smith   void               *addr;
563*5c6c1daeSBarry Smith 
564*5c6c1daeSBarry Smith   ierr = PetscGetHostName(host,256);CHKERRQ(ierr);
565*5c6c1daeSBarry Smith   ierr = AMS_Connect(host, -1, &comm_list);CHKERRQ(ierr);
566*5c6c1daeSBarry Smith   ierr = PetscWebSendHeader(fd, 200, "OK", NULL, "text/html", -1);CHKERRQ(ierr);
567*5c6c1daeSBarry Smith   if (!comm_list || !comm_list[0]) {
568*5c6c1daeSBarry Smith     fprintf(fd, "AMS Communicator not running</p>\r\n");
569*5c6c1daeSBarry Smith   } else {
570*5c6c1daeSBarry Smith     ierr = AMS_Comm_attach(comm_list[0],&ams);CHKERRQ(ierr);
571*5c6c1daeSBarry Smith     ierr = AMS_Comm_get_memory_list(ams,&mem_list);CHKERRQ(ierr);
572*5c6c1daeSBarry Smith     if (!mem_list[0]) {
573*5c6c1daeSBarry Smith       fprintf(fd, "AMS Communicator %s has no published memories</p>\r\n",comm_list[0]);
574*5c6c1daeSBarry Smith     } else {
575*5c6c1daeSBarry Smith       fprintf(fd, "<HTML><HEAD><TITLE>Petsc Application Server</TITLE></HEAD>\r\n<BODY>");
576*5c6c1daeSBarry Smith       fprintf(fd,"<ul>\r\n");
577*5c6c1daeSBarry Smith       while (mem_list[i]) {
578*5c6c1daeSBarry Smith 	fprintf(fd,"<li> %s</li>\r\n",mem_list[i]);
579*5c6c1daeSBarry Smith 	ierr = AMS_Memory_attach(ams,mem_list[i],&memory,NULL);CHKERRQ(ierr);
580*5c6c1daeSBarry Smith 	ierr = AMS_Memory_get_field_list(memory, &fld_list);CHKERRQ(ierr);
581*5c6c1daeSBarry Smith 	j = 0;
582*5c6c1daeSBarry Smith 	fprintf(fd,"<ul>\r\n");
583*5c6c1daeSBarry Smith 	while (fld_list[j]) {
584*5c6c1daeSBarry Smith 	  fprintf(fd,"<li> %s",fld_list[j]);
585*5c6c1daeSBarry Smith 	  ierr = AMS_Memory_get_field_info(memory, fld_list[j], &addr, &len, &dtype, &mtype, &stype, &rtype);CHKERRQ(ierr);
586*5c6c1daeSBarry Smith 	  if (len == 1) {
587*5c6c1daeSBarry Smith 	    if (dtype == AMS_INT)        fprintf(fd," %d",*(int*)addr);
588*5c6c1daeSBarry Smith 	    else if (dtype == AMS_STRING) fprintf(fd," %s",*(char**)addr);
589*5c6c1daeSBarry Smith 	  }
590*5c6c1daeSBarry Smith 	  fprintf(fd,"</li>\r\n");
591*5c6c1daeSBarry Smith 	  j++;
592*5c6c1daeSBarry Smith 	}
593*5c6c1daeSBarry Smith 	fprintf(fd,"</ul>\r\n");
594*5c6c1daeSBarry Smith 	i++;
595*5c6c1daeSBarry Smith       }
596*5c6c1daeSBarry Smith       fprintf(fd,"</ul>\r\n");
597*5c6c1daeSBarry Smith     }
598*5c6c1daeSBarry Smith   }
599*5c6c1daeSBarry Smith   ierr = PetscWebSendFooter(fd);CHKERRQ(ierr);
600*5c6c1daeSBarry Smith   ierr = AMS_Disconnect();CHKERRQ(ierr);
601*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
602*5c6c1daeSBarry Smith }
603*5c6c1daeSBarry Smith 
604*5c6c1daeSBarry Smith #undef __FUNCT__
605*5c6c1daeSBarry Smith #define __FUNCT__ "PetscAMSDisplayTree"
606*5c6c1daeSBarry Smith PetscErrorCode PetscAMSDisplayTree(FILE *fd)
607*5c6c1daeSBarry Smith {
608*5c6c1daeSBarry Smith   PetscErrorCode     ierr;
609*5c6c1daeSBarry Smith   char               host[256],**comm_list,**mem_list,**fld_list;
610*5c6c1daeSBarry Smith   AMS_Comm           ams;
611*5c6c1daeSBarry Smith   PetscInt           i = 0,j;
612*5c6c1daeSBarry Smith   AMS_Memory_type    mtype;
613*5c6c1daeSBarry Smith   AMS_Data_type      dtype;
614*5c6c1daeSBarry Smith   AMS_Shared_type    stype;
615*5c6c1daeSBarry Smith   AMS_Reduction_type rtype;
616*5c6c1daeSBarry Smith   AMS_Memory         memory;
617*5c6c1daeSBarry Smith   int                len;
618*5c6c1daeSBarry Smith   void               *addr2,*addr3,*addr,*addr4;
619*5c6c1daeSBarry Smith 
620*5c6c1daeSBarry Smith   ierr = PetscGetHostName(host,256);CHKERRQ(ierr);
621*5c6c1daeSBarry Smith   ierr = AMS_Connect(host, -1, &comm_list);CHKERRQ(ierr);
622*5c6c1daeSBarry Smith   ierr = PetscWebSendHeader(fd, 200, "OK", NULL, "text/html", -1);CHKERRQ(ierr);
623*5c6c1daeSBarry Smith   if (!comm_list || !comm_list[0]) {
624*5c6c1daeSBarry Smith     fprintf(fd, "AMS Communicator not running</p>\r\n");
625*5c6c1daeSBarry Smith   } else {
626*5c6c1daeSBarry Smith     ierr = AMS_Comm_attach(comm_list[0],&ams);CHKERRQ(ierr);
627*5c6c1daeSBarry Smith     ierr = AMS_Comm_get_memory_list(ams,&mem_list);CHKERRQ(ierr);
628*5c6c1daeSBarry Smith     if (!mem_list[0]) {
629*5c6c1daeSBarry Smith       fprintf(fd, "AMS Communicator %s has no published memories</p>\r\n",comm_list[0]);
630*5c6c1daeSBarry Smith     } else {
631*5c6c1daeSBarry Smith       PetscInt   Nlevels,*Level,*Levelcnt,*Idbylevel,*Column,*parentid,*Id,maxId = 0,maxCol = 0,*parentId,id,cnt,Nlevelcnt = 0;
632*5c6c1daeSBarry Smith       PetscBool  *mask;
633*5c6c1daeSBarry Smith       char       **classes,*clas,**subclasses,*sclas;
634*5c6c1daeSBarry Smith 
635*5c6c1daeSBarry Smith       /* get maximum number of objects */
636*5c6c1daeSBarry Smith       while (mem_list[i]) {
637*5c6c1daeSBarry Smith 	ierr = AMS_Memory_attach(ams,mem_list[i],&memory,NULL);CHKERRQ(ierr);
638*5c6c1daeSBarry Smith 	ierr = AMS_Memory_get_field_list(memory, &fld_list);CHKERRQ(ierr);
639*5c6c1daeSBarry Smith         ierr = AMS_Memory_get_field_info(memory, "Id", &addr2, &len, &dtype, &mtype, &stype, &rtype);CHKERRQ(ierr);
640*5c6c1daeSBarry Smith         Id = (int*) addr2;
641*5c6c1daeSBarry Smith         maxId = PetscMax(maxId,*Id);
642*5c6c1daeSBarry Smith 	i++;
643*5c6c1daeSBarry Smith       }
644*5c6c1daeSBarry Smith       maxId++;
645*5c6c1daeSBarry Smith 
646*5c6c1daeSBarry Smith       /* Gets everyone's parent ID and which nodes are masked */
647*5c6c1daeSBarry Smith       ierr = PetscMalloc4(maxId,PetscInt,&parentid,maxId,PetscBool ,&mask,maxId,char**,&classes,maxId,char**,&subclasses);CHKERRQ(ierr);
648*5c6c1daeSBarry Smith       ierr = PetscMemzero(classes,maxId*sizeof(char*));CHKERRQ(ierr);
649*5c6c1daeSBarry Smith       ierr = PetscMemzero(subclasses,maxId*sizeof(char*));CHKERRQ(ierr);
650*5c6c1daeSBarry Smith       for (i=0; i<maxId; i++) mask[i] = PETSC_TRUE;
651*5c6c1daeSBarry Smith       i = 0;
652*5c6c1daeSBarry Smith       while (mem_list[i]) {
653*5c6c1daeSBarry Smith 	ierr = AMS_Memory_attach(ams,mem_list[i],&memory,NULL);CHKERRQ(ierr);
654*5c6c1daeSBarry Smith 	ierr = AMS_Memory_get_field_list(memory, &fld_list);CHKERRQ(ierr);
655*5c6c1daeSBarry Smith         ierr = AMS_Memory_get_field_info(memory, "Id", &addr2, &len, &dtype, &mtype, &stype, &rtype);CHKERRQ(ierr);
656*5c6c1daeSBarry Smith         Id = (int*) addr2;
657*5c6c1daeSBarry Smith 	ierr = AMS_Memory_get_field_info(memory, "ParentId", &addr3, &len, &dtype, &mtype, &stype, &rtype);CHKERRQ(ierr);
658*5c6c1daeSBarry Smith 	parentId = (int*) addr3;
659*5c6c1daeSBarry Smith 	ierr = AMS_Memory_get_field_info(memory, "Class", &addr, &len, &dtype, &mtype, &stype, &rtype);CHKERRQ(ierr);
660*5c6c1daeSBarry Smith         clas = *(char**)addr;
661*5c6c1daeSBarry Smith 	ierr = AMS_Memory_get_field_info(memory, "Type", &addr4, &len, &dtype, &mtype, &stype, &rtype);CHKERRQ(ierr);
662*5c6c1daeSBarry Smith         sclas = *(char**)addr4;
663*5c6c1daeSBarry Smith         parentid[*Id] = *parentId;
664*5c6c1daeSBarry Smith 	mask[*Id]     = PETSC_FALSE;
665*5c6c1daeSBarry Smith         ierr = PetscStrallocpy(clas,classes+*Id);CHKERRQ(ierr);
666*5c6c1daeSBarry Smith         ierr = PetscStrallocpy(sclas,subclasses+*Id);CHKERRQ(ierr);
667*5c6c1daeSBarry Smith         i++;
668*5c6c1daeSBarry Smith       }
669*5c6c1daeSBarry Smith 
670*5c6c1daeSBarry Smith       /* if the parent is masked then relabel the parent as 0 since the true parent was deleted */
671*5c6c1daeSBarry Smith       for (i=0; i<maxId; i++) {
672*5c6c1daeSBarry Smith         if (!mask[i] && parentid[i] > 0 && mask[parentid[i]]) parentid[i] = 0;
673*5c6c1daeSBarry Smith       }
674*5c6c1daeSBarry Smith 
675*5c6c1daeSBarry Smith       ierr = PetscProcessTree(maxId,mask,parentid,&Nlevels,&Level,&Levelcnt,&Idbylevel,&Column);CHKERRQ(ierr);
676*5c6c1daeSBarry Smith 
677*5c6c1daeSBarry Smith       for (i=0; i<Nlevels; i++) {
678*5c6c1daeSBarry Smith         maxCol = PetscMax(maxCol,Levelcnt[i]);
679*5c6c1daeSBarry Smith       }
680*5c6c1daeSBarry Smith       for (i=0; i<Nlevels; i++) {
681*5c6c1daeSBarry Smith         Nlevelcnt = PetscMax(Nlevelcnt,Levelcnt[i]);
682*5c6c1daeSBarry Smith       }
683*5c6c1daeSBarry Smith 
684*5c6c1daeSBarry Smith       /* print all the top-level objects */
685*5c6c1daeSBarry Smith       fprintf(fd, "<HTML><HEAD><TITLE>Petsc Application Server</TITLE>\r\n");
686*5c6c1daeSBarry Smith       fprintf(fd, "<canvas width=800 height=600 id=\"tree\"></canvas>\r\n");
687*5c6c1daeSBarry Smith       fprintf(fd, "<script type=\"text/javascript\">\r\n");
688*5c6c1daeSBarry Smith       fprintf(fd, "  function draw(){\r\n");
689*5c6c1daeSBarry Smith       fprintf(fd, "  var example = document.getElementById('tree');\r\n");
690*5c6c1daeSBarry Smith       fprintf(fd, "  var context = example.getContext('2d');\r\n");
691*5c6c1daeSBarry Smith       /* adjust font size based on how big a tree is printed */
692*5c6c1daeSBarry Smith       if (Nlevels > 5 || Nlevelcnt > 10) {
693*5c6c1daeSBarry Smith         fprintf(fd, "  context.font         = \"normal 12px sans-serif\";\r\n");
694*5c6c1daeSBarry Smith       } else {
695*5c6c1daeSBarry Smith         fprintf(fd, "  context.font         = \"normal 24px sans-serif\";\r\n");
696*5c6c1daeSBarry Smith       }
697*5c6c1daeSBarry Smith       fprintf(fd, "  context.fillStyle = \"rgb(255,0,0)\";\r\n");
698*5c6c1daeSBarry Smith       fprintf(fd, "  context.textBaseline = \"top\";\r\n");
699*5c6c1daeSBarry Smith       fprintf(fd, "  var xspacep = 0;\r\n");
700*5c6c1daeSBarry Smith       fprintf(fd, "  var yspace = example.height/%d;\r\n",(Nlevels+1));
701*5c6c1daeSBarry Smith       /* estimate the height of a string as twice the width of a character */
702*5c6c1daeSBarry Smith       fprintf(fd, "  var wheight = context.measureText(\"K\");\r\n");
703*5c6c1daeSBarry Smith       fprintf(fd, "  var height = 1.6*wheight.width;\r\n");
704*5c6c1daeSBarry Smith 
705*5c6c1daeSBarry Smith       cnt = 0;
706*5c6c1daeSBarry Smith       for (i=0; i<Nlevels; i++) {
707*5c6c1daeSBarry Smith 	fprintf(fd, "  var xspace = example.width/%d;\r\n",Levelcnt[i]+1);
708*5c6c1daeSBarry Smith 	for (j=0; j<Levelcnt[i]; j++) {
709*5c6c1daeSBarry Smith           id   = Idbylevel[cnt++];
710*5c6c1daeSBarry Smith           clas  = classes[id];
711*5c6c1daeSBarry Smith           sclas = subclasses[id];
712*5c6c1daeSBarry Smith 	  fprintf(fd, "  var width = context.measureText(\"%s\");\r\n",clas);
713*5c6c1daeSBarry Smith 	  fprintf(fd, "  var swidth = context.measureText(\"%s\");\r\n",sclas);
714*5c6c1daeSBarry Smith 	  fprintf(fd, "  context.fillStyle = \"rgb(255,0,0)\";\r\n");
715*5c6c1daeSBarry Smith 	  fprintf(fd, "  context.fillRect((%d)*xspace-width.width/2, %d*yspace-height/2, width.width, height);\r\n",j+1,i+1);
716*5c6c1daeSBarry Smith 	  fprintf(fd, "  context.fillRect((%d)*xspace-swidth.width/2, %d*yspace+height/2, swidth.width, height);\r\n",j+1,i+1);
717*5c6c1daeSBarry Smith 	  fprintf(fd, "  context.fillStyle = \"rgb(0,0,0)\";\r\n");
718*5c6c1daeSBarry Smith 	  fprintf(fd, "  context.fillText(\"%s\",(%d)*xspace-width.width/2, %d*yspace-height/2);\r\n",clas,j+1,i+1);
719*5c6c1daeSBarry Smith 	  fprintf(fd, "  context.fillText(\"%s\",(%d)*xspace-swidth.width/2, %d*yspace+height/2);\r\n",sclas,j+1,i+1);
720*5c6c1daeSBarry Smith           if (parentid[id]) {
721*5c6c1daeSBarry Smith 	    fprintf(fd, "  context.moveTo(%d*xspace,%d*yspace-height/2);\r\n",j+1,i+1);
722*5c6c1daeSBarry Smith 	    fprintf(fd, "  context.lineTo(%d*xspacep,%d*yspace+3*height/2);\r\n",Column[parentid[id]]+1,i);
723*5c6c1daeSBarry Smith 	    fprintf(fd, "  context.stroke();\r\n");
724*5c6c1daeSBarry Smith           }
725*5c6c1daeSBarry Smith 	}
726*5c6c1daeSBarry Smith 	fprintf(fd, "  xspacep = xspace;\r\n");
727*5c6c1daeSBarry Smith       }
728*5c6c1daeSBarry Smith       ierr = PetscFree(Level);CHKERRQ(ierr);
729*5c6c1daeSBarry Smith       ierr = PetscFree(Levelcnt);CHKERRQ(ierr);
730*5c6c1daeSBarry Smith       ierr = PetscFree(Idbylevel);CHKERRQ(ierr);
731*5c6c1daeSBarry Smith       ierr = PetscFree(Column);CHKERRQ(ierr);
732*5c6c1daeSBarry Smith       for (i=0; i<maxId; i++) {
733*5c6c1daeSBarry Smith         ierr = PetscFree(classes[i]);CHKERRQ(ierr);
734*5c6c1daeSBarry Smith         ierr = PetscFree(subclasses[i]);CHKERRQ(ierr);
735*5c6c1daeSBarry Smith       }
736*5c6c1daeSBarry Smith       ierr = PetscFree4(mask,parentid,classes,subclasses);CHKERRQ(ierr);
737*5c6c1daeSBarry Smith 
738*5c6c1daeSBarry Smith       ierr = AMS_Disconnect();CHKERRQ(ierr);
739*5c6c1daeSBarry Smith       fprintf(fd, "}\r\n");
740*5c6c1daeSBarry Smith       fprintf(fd, "</script>\r\n");
741*5c6c1daeSBarry Smith       fprintf(fd, "<body onload=\"draw();\">\r\n");
742*5c6c1daeSBarry Smith       fprintf(fd, "</body></html>\r\n");
743*5c6c1daeSBarry Smith     }
744*5c6c1daeSBarry Smith   }
745*5c6c1daeSBarry Smith   ierr = PetscWebSendFooter(fd);CHKERRQ(ierr);
746*5c6c1daeSBarry Smith 
747*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
748*5c6c1daeSBarry Smith }
749*5c6c1daeSBarry Smith #endif
750*5c6c1daeSBarry Smith 
751*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_YAML)
752*5c6c1daeSBarry Smith 
753*5c6c1daeSBarry Smith EXTERN_C_BEGIN
754*5c6c1daeSBarry Smith /*
755*5c6c1daeSBarry Smith     Toy function that returns all the arguments it is passed
756*5c6c1daeSBarry Smith */
757*5c6c1daeSBarry Smith #undef __FUNCT__
758*5c6c1daeSBarry Smith #define __FUNCT__ "YAML_echo"
759*5c6c1daeSBarry Smith PetscErrorCode YAML_echo(PetscInt argc,char **args,PetscInt *argco,char ***argso)
760*5c6c1daeSBarry Smith {
761*5c6c1daeSBarry Smith   PetscErrorCode ierr;
762*5c6c1daeSBarry Smith   PetscInt       i;
763*5c6c1daeSBarry Smith 
764*5c6c1daeSBarry Smith   ierr = PetscPrintf(PETSC_COMM_SELF,"Number of arguments to function %d\n",argc);CHKERRQ(ierr);
765*5c6c1daeSBarry Smith   for (i=0; i<argc; i++) {
766*5c6c1daeSBarry Smith     ierr = PetscPrintf(PETSC_COMM_SELF,"  %s\n",args[i]);CHKERRQ(ierr);
767*5c6c1daeSBarry Smith   }
768*5c6c1daeSBarry Smith   *argco = argc;
769*5c6c1daeSBarry Smith   ierr = PetscMalloc(argc*sizeof(char*),argso);CHKERRQ(ierr);
770*5c6c1daeSBarry Smith   for (i=0; i<argc; i++) {
771*5c6c1daeSBarry Smith     ierr = PetscStrallocpy(args[i],&(*argso)[i]);CHKERRQ(ierr);
772*5c6c1daeSBarry Smith   }
773*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
774*5c6c1daeSBarry Smith }
775*5c6c1daeSBarry Smith EXTERN_C_END
776*5c6c1daeSBarry Smith 
777*5c6c1daeSBarry Smith EXTERN_C_BEGIN
778*5c6c1daeSBarry Smith #undef __FUNCT__
779*5c6c1daeSBarry Smith #define __FUNCT__ "YAML_AMS_Connect"
780*5c6c1daeSBarry Smith /*
781*5c6c1daeSBarry Smith       Connects to the local AMS and gets only the first communication name
782*5c6c1daeSBarry Smith 
783*5c6c1daeSBarry Smith    Input Parameters:
784*5c6c1daeSBarry Smith .     none
785*5c6c1daeSBarry Smith 
786*5c6c1daeSBarry Smith    Output Parameter:
787*5c6c1daeSBarry Smith .     oarg1 - the string name of the first communicator
788*5c6c1daeSBarry Smith 
789*5c6c1daeSBarry Smith */
790*5c6c1daeSBarry Smith PetscErrorCode YAML_AMS_Connect(PetscInt argc,char **args,PetscInt *argco,char ***argso)
791*5c6c1daeSBarry Smith {
792*5c6c1daeSBarry Smith   PetscErrorCode ierr;
793*5c6c1daeSBarry Smith   char           **list = 0;
794*5c6c1daeSBarry Smith 
795*5c6c1daeSBarry Smith   PetscFunctionBegin;
796*5c6c1daeSBarry Smith   ierr = AMS_Connect(0,-1,&list);
797*5c6c1daeSBarry Smith   if (ierr) {ierr = PetscInfo1(PETSC_NULL,"AMS_Connect() error %d\n",ierr);CHKERRQ(ierr);}
798*5c6c1daeSBarry Smith   else if (!list) {ierr = PetscInfo(PETSC_NULL,"AMS_Connect() list empty, not running AMS server\n");CHKERRQ(ierr);}
799*5c6c1daeSBarry Smith   *argco = 1;
800*5c6c1daeSBarry Smith   ierr = PetscMalloc(sizeof(char*),argso);CHKERRQ(ierr);
801*5c6c1daeSBarry Smith   if (list){
802*5c6c1daeSBarry Smith     ierr = PetscStrallocpy(list[0],&(*argso)[0]);CHKERRQ(ierr);
803*5c6c1daeSBarry Smith   } else {
804*5c6c1daeSBarry Smith     ierr = PetscStrallocpy("No AMS publisher running",&(*argso)[0]);CHKERRQ(ierr);
805*5c6c1daeSBarry Smith   }
806*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
807*5c6c1daeSBarry Smith }
808*5c6c1daeSBarry Smith EXTERN_C_END
809*5c6c1daeSBarry Smith 
810*5c6c1daeSBarry Smith EXTERN_C_BEGIN
811*5c6c1daeSBarry Smith #undef __FUNCT__
812*5c6c1daeSBarry Smith #define __FUNCT__ "YAML_AMS_Comm_attach"
813*5c6c1daeSBarry Smith /*
814*5c6c1daeSBarry Smith       Attaches to an AMS communicator
815*5c6c1daeSBarry Smith 
816*5c6c1daeSBarry Smith    Input Parameter:
817*5c6c1daeSBarry Smith .     arg1 - string name of the communicator
818*5c6c1daeSBarry Smith 
819*5c6c1daeSBarry Smith    Output Parameter:
820*5c6c1daeSBarry Smith .     oarg1 - the integer name of the communicator
821*5c6c1daeSBarry Smith 
822*5c6c1daeSBarry Smith */
823*5c6c1daeSBarry Smith PetscErrorCode YAML_AMS_Comm_attach(PetscInt argc,char **args,PetscInt *argco,char ***argso)
824*5c6c1daeSBarry Smith {
825*5c6c1daeSBarry Smith   PetscErrorCode ierr;
826*5c6c1daeSBarry Smith   AMS_Comm       comm = -1;
827*5c6c1daeSBarry Smith 
828*5c6c1daeSBarry Smith   PetscFunctionBegin;
829*5c6c1daeSBarry Smith   ierr = AMS_Comm_attach(args[0],&comm);
830*5c6c1daeSBarry Smith   if (ierr) {ierr = PetscInfo1(PETSC_NULL,"AMS_Comm_attach() error %d\n",ierr);CHKERRQ(ierr);}
831*5c6c1daeSBarry Smith   *argco = 1;
832*5c6c1daeSBarry Smith   ierr = PetscMalloc(sizeof(char*),argso);CHKERRQ(ierr);
833*5c6c1daeSBarry Smith   ierr = PetscMalloc(3*sizeof(char*),&argso[0][0]);CHKERRQ(ierr);
834*5c6c1daeSBarry Smith   sprintf(argso[0][0],"%d",(int)comm);
835*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
836*5c6c1daeSBarry Smith }
837*5c6c1daeSBarry Smith EXTERN_C_END
838*5c6c1daeSBarry Smith 
839*5c6c1daeSBarry Smith EXTERN_C_BEGIN
840*5c6c1daeSBarry Smith #undef __FUNCT__
841*5c6c1daeSBarry Smith #define __FUNCT__ "YAML_AMS_Comm_get_memory_list"
842*5c6c1daeSBarry Smith /*
843*5c6c1daeSBarry Smith       Gets the list of memories on an AMS Comm
844*5c6c1daeSBarry Smith 
845*5c6c1daeSBarry Smith    Input Parameter:
846*5c6c1daeSBarry Smith .     arg1 - integer name of the communicator
847*5c6c1daeSBarry Smith 
848*5c6c1daeSBarry Smith    Output Parameter:
849*5c6c1daeSBarry Smith .     oarg1 - the list of names
850*5c6c1daeSBarry Smith 
851*5c6c1daeSBarry Smith */
852*5c6c1daeSBarry Smith PetscErrorCode YAML_AMS_Comm_get_memory_list(PetscInt argc,char **args,PetscInt *argco,char ***argso)
853*5c6c1daeSBarry Smith {
854*5c6c1daeSBarry Smith   PetscErrorCode ierr;
855*5c6c1daeSBarry Smith   char           **mem_list;
856*5c6c1daeSBarry Smith   AMS_Comm       comm;
857*5c6c1daeSBarry Smith   PetscInt       i,iargco = 0;
858*5c6c1daeSBarry Smith 
859*5c6c1daeSBarry Smith   PetscFunctionBegin;
860*5c6c1daeSBarry Smith   sscanf(args[0],"%d",&comm);
861*5c6c1daeSBarry Smith   ierr = AMS_Comm_get_memory_list(comm,&mem_list);
862*5c6c1daeSBarry Smith   if (ierr) {
863*5c6c1daeSBarry Smith     ierr = PetscInfo1(PETSC_NULL,"AMS_Comm_get_memory_list() error %d\n",ierr);CHKERRQ(ierr);
864*5c6c1daeSBarry Smith   } else {
865*5c6c1daeSBarry Smith     while (mem_list[iargco++]) ;
866*5c6c1daeSBarry Smith     iargco--;
867*5c6c1daeSBarry Smith 
868*5c6c1daeSBarry Smith     ierr = PetscMalloc((iargco)*sizeof(char*),argso);CHKERRQ(ierr);
869*5c6c1daeSBarry Smith     for (i=0; i<iargco; i++) {
870*5c6c1daeSBarry Smith       ierr = PetscStrallocpy(mem_list[i],(*argso)+i);CHKERRQ(ierr);
871*5c6c1daeSBarry Smith     }
872*5c6c1daeSBarry Smith   }
873*5c6c1daeSBarry Smith   *argco = iargco;
874*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
875*5c6c1daeSBarry Smith }
876*5c6c1daeSBarry Smith EXTERN_C_END
877*5c6c1daeSBarry Smith 
878*5c6c1daeSBarry Smith EXTERN_C_BEGIN
879*5c6c1daeSBarry Smith #undef __FUNCT__
880*5c6c1daeSBarry Smith #define __FUNCT__ "YAML_AMS_Memory_attach"
881*5c6c1daeSBarry Smith /*
882*5c6c1daeSBarry Smith       Attaches to an AMS memory in a communicator
883*5c6c1daeSBarry Smith 
884*5c6c1daeSBarry Smith    Input Parameter:
885*5c6c1daeSBarry Smith .     arg1 - communicator
886*5c6c1daeSBarry Smith .     arg2 - string name of the memory
887*5c6c1daeSBarry Smith 
888*5c6c1daeSBarry Smith    Output Parameter:
889*5c6c1daeSBarry Smith .     oarg1 - the integer name of the memory
890*5c6c1daeSBarry Smith .     oarg2 - the integer step of the memory
891*5c6c1daeSBarry Smith 
892*5c6c1daeSBarry Smith */
893*5c6c1daeSBarry Smith PetscErrorCode YAML_AMS_Memory_attach(PetscInt argc,char **args,PetscInt *argco,char ***argso)
894*5c6c1daeSBarry Smith {
895*5c6c1daeSBarry Smith   PetscErrorCode ierr;
896*5c6c1daeSBarry Smith   AMS_Comm       comm;
897*5c6c1daeSBarry Smith   AMS_Memory     mem;
898*5c6c1daeSBarry Smith   unsigned int   step;
899*5c6c1daeSBarry Smith 
900*5c6c1daeSBarry Smith   PetscFunctionBegin;
901*5c6c1daeSBarry Smith   sscanf(args[0],"%d",&comm);
902*5c6c1daeSBarry Smith   ierr = AMS_Memory_attach(comm,args[1],&mem,&step);
903*5c6c1daeSBarry Smith   if (ierr) {ierr = PetscInfo1(PETSC_NULL,"AMS_Memory_attach() error %d\n",ierr);CHKERRQ(ierr);}
904*5c6c1daeSBarry Smith   *argco = 2;
905*5c6c1daeSBarry Smith   ierr = PetscMalloc(2*sizeof(char*),argso);CHKERRQ(ierr);
906*5c6c1daeSBarry Smith   ierr = PetscMalloc(3*sizeof(char*),&argso[0][0]);CHKERRQ(ierr);
907*5c6c1daeSBarry Smith   sprintf(argso[0][0],"%d",(int)mem);
908*5c6c1daeSBarry Smith   ierr = PetscMalloc(3*sizeof(char*),&argso[0][1]);CHKERRQ(ierr);
909*5c6c1daeSBarry Smith   sprintf(argso[0][1],"%d",(int)step);
910*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
911*5c6c1daeSBarry Smith }
912*5c6c1daeSBarry Smith EXTERN_C_END
913*5c6c1daeSBarry Smith 
914*5c6c1daeSBarry Smith EXTERN_C_BEGIN
915*5c6c1daeSBarry Smith #undef __FUNCT__
916*5c6c1daeSBarry Smith #define __FUNCT__ "YAML_AMS_Memory_get_field_list"
917*5c6c1daeSBarry Smith /*
918*5c6c1daeSBarry Smith       Gets the list of fields on an AMS Memory
919*5c6c1daeSBarry Smith 
920*5c6c1daeSBarry Smith    Input Parameter:
921*5c6c1daeSBarry Smith .     arg1 - integer name of the memory
922*5c6c1daeSBarry Smith 
923*5c6c1daeSBarry Smith    Output Parameter:
924*5c6c1daeSBarry Smith .     oarg1 - the list of names
925*5c6c1daeSBarry Smith 
926*5c6c1daeSBarry Smith */
927*5c6c1daeSBarry Smith PetscErrorCode YAML_AMS_Memory_get_field_list(PetscInt argc,char **args,PetscInt *argco,char ***argso)
928*5c6c1daeSBarry Smith {
929*5c6c1daeSBarry Smith   PetscErrorCode ierr;
930*5c6c1daeSBarry Smith   char           **field_list;
931*5c6c1daeSBarry Smith   AMS_Memory     mem;
932*5c6c1daeSBarry Smith   PetscInt       i,iargco = 0;
933*5c6c1daeSBarry Smith 
934*5c6c1daeSBarry Smith   PetscFunctionBegin;
935*5c6c1daeSBarry Smith   sscanf(args[0],"%d",&mem);
936*5c6c1daeSBarry Smith   ierr = AMS_Memory_get_field_list(mem,&field_list);
937*5c6c1daeSBarry Smith   if (ierr) {
938*5c6c1daeSBarry Smith     ierr = PetscInfo1(PETSC_NULL,"AMS_Memory_get_field_list() error %d\n",ierr);CHKERRQ(ierr);
939*5c6c1daeSBarry Smith   } else {
940*5c6c1daeSBarry Smith     while (field_list[iargco++]) ;
941*5c6c1daeSBarry Smith     iargco--;
942*5c6c1daeSBarry Smith 
943*5c6c1daeSBarry Smith     ierr = PetscMalloc((iargco)*sizeof(char*),argso);CHKERRQ(ierr);
944*5c6c1daeSBarry Smith     for (i=0; i<iargco; i++) {
945*5c6c1daeSBarry Smith       ierr = PetscStrallocpy(field_list[i],(*argso)+i);CHKERRQ(ierr);
946*5c6c1daeSBarry Smith     }
947*5c6c1daeSBarry Smith   }
948*5c6c1daeSBarry Smith   *argco = iargco;
949*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
950*5c6c1daeSBarry Smith }
951*5c6c1daeSBarry Smith EXTERN_C_END
952*5c6c1daeSBarry Smith 
953*5c6c1daeSBarry Smith const char *AMS_Data_types[] = {"AMS_DATA_UNDEF","AMS_BOOLEAN","AMS_INT","AMS_FLOAT","AMS_DOUBLE","AMS_STRING","AMS_Data_type","AMS_",0};
954*5c6c1daeSBarry Smith const char *AMS_Memory_types[] = {"AMS_MEMORY_UNDEF","AMS_READ","AMS_WRITE","AMS_Memory_type","AMS_",0};
955*5c6c1daeSBarry Smith const char *AMS_Shared_types[] = {"AMS_SHARED_UNDEF","AMS_COMMON","AMS_REDUCED","AMS_DISTRIBUTED","AMS_Shared_type","AMS_",0};
956*5c6c1daeSBarry Smith const char *AMS_Reduction_types[] = {"AMS_REDUCTION_WHY_NOT_UNDEF?","AMS_SUM","AMS_MAX","AMS_MIN","AMS_REDUCTION_UNDEF","AMS_Reduction_type","AMS_",0};
957*5c6c1daeSBarry Smith 
958*5c6c1daeSBarry Smith EXTERN_C_BEGIN
959*5c6c1daeSBarry Smith #undef __FUNCT__
960*5c6c1daeSBarry Smith #define __FUNCT__ "YAML_AMS_Memory_get_field_info"
961*5c6c1daeSBarry Smith /*
962*5c6c1daeSBarry Smith       Gets information about a field
963*5c6c1daeSBarry Smith 
964*5c6c1daeSBarry Smith    Input Parameter:
965*5c6c1daeSBarry Smith .     arg1 - memory
966*5c6c1daeSBarry Smith .     arg2 - string name of the field
967*5c6c1daeSBarry Smith 
968*5c6c1daeSBarry Smith    Output Parameter:
969*5c6c1daeSBarry Smith 
970*5c6c1daeSBarry Smith */
971*5c6c1daeSBarry Smith PetscErrorCode YAML_AMS_Memory_get_field_info(PetscInt argc,char **args,PetscInt *argco,char ***argso)
972*5c6c1daeSBarry Smith {
973*5c6c1daeSBarry Smith   PetscErrorCode     ierr;
974*5c6c1daeSBarry Smith   AMS_Memory         mem;
975*5c6c1daeSBarry Smith   void               *addr;
976*5c6c1daeSBarry Smith   int                len;
977*5c6c1daeSBarry Smith   AMS_Data_type      dtype;
978*5c6c1daeSBarry Smith   AMS_Memory_type    mtype;
979*5c6c1daeSBarry Smith   AMS_Shared_type    stype;
980*5c6c1daeSBarry Smith   AMS_Reduction_type rtype;
981*5c6c1daeSBarry Smith   PetscInt           i;
982*5c6c1daeSBarry Smith 
983*5c6c1daeSBarry Smith   PetscFunctionBegin;
984*5c6c1daeSBarry Smith   sscanf(args[0],"%d",&mem);
985*5c6c1daeSBarry Smith   ierr = AMS_Memory_get_field_info(mem,args[1],&addr,&len,&dtype,&mtype,&stype,&rtype);
986*5c6c1daeSBarry Smith   if (ierr) {ierr = PetscInfo1(PETSC_NULL,"AMS_Memory_get_field_info() error %d\n",ierr);CHKERRQ(ierr);}
987*5c6c1daeSBarry Smith   *argco = 4 + len;
988*5c6c1daeSBarry Smith   ierr = PetscMalloc((*argco)*sizeof(char*),argso);CHKERRQ(ierr);
989*5c6c1daeSBarry Smith   ierr = PetscStrallocpy(AMS_Data_types[dtype],&argso[0][0]);CHKERRQ(ierr);
990*5c6c1daeSBarry Smith   ierr = PetscStrallocpy(AMS_Memory_types[mtype],&argso[0][1]);CHKERRQ(ierr);
991*5c6c1daeSBarry Smith   ierr = PetscStrallocpy(AMS_Shared_types[stype],&argso[0][2]);CHKERRQ(ierr);
992*5c6c1daeSBarry Smith   ierr = PetscStrallocpy(AMS_Reduction_types[rtype],&argso[0][3]);CHKERRQ(ierr);
993*5c6c1daeSBarry Smith   for (i=0; i<len; i++) {
994*5c6c1daeSBarry Smith     if (dtype == AMS_STRING) {
995*5c6c1daeSBarry Smith       ierr = PetscStrallocpy(*(const char **)addr,&argso[0][4+i]);CHKERRQ(ierr);
996*5c6c1daeSBarry Smith     } else if (dtype == AMS_DOUBLE) {
997*5c6c1daeSBarry Smith       ierr = PetscMalloc(20*sizeof(char),&argso[0][4+i]);CHKERRQ(ierr);
998*5c6c1daeSBarry Smith       sprintf(argso[0][4+i],"%18.16e",*(double*)addr);
999*5c6c1daeSBarry Smith     } else if (dtype == AMS_INT) {
1000*5c6c1daeSBarry Smith       ierr = PetscMalloc(10*sizeof(char),&argso[0][4+i]);CHKERRQ(ierr);
1001*5c6c1daeSBarry Smith       sprintf(argso[0][4+i],"%d",*(int*)addr);
1002*5c6c1daeSBarry Smith     } else if (dtype == AMS_BOOLEAN) {
1003*5c6c1daeSBarry Smith       if (*(int*)addr) {
1004*5c6c1daeSBarry Smith         ierr = PetscStrallocpy("true",&argso[0][4+i]);CHKERRQ(ierr);
1005*5c6c1daeSBarry Smith       } else {
1006*5c6c1daeSBarry Smith         ierr = PetscStrallocpy("false",&argso[0][4+i]);CHKERRQ(ierr);
1007*5c6c1daeSBarry Smith       }
1008*5c6c1daeSBarry Smith     } else {
1009*5c6c1daeSBarry Smith       ierr = PetscStrallocpy("Not yet done",&argso[0][4+i]);CHKERRQ(ierr);
1010*5c6c1daeSBarry Smith     }
1011*5c6c1daeSBarry Smith   }
1012*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
1013*5c6c1daeSBarry Smith }
1014*5c6c1daeSBarry Smith EXTERN_C_END
1015*5c6c1daeSBarry Smith 
1016*5c6c1daeSBarry Smith #include "yaml.h"
1017*5c6c1daeSBarry Smith #undef __FUNCT__
1018*5c6c1daeSBarry Smith #define __FUNCT__ "PetscProcessYAMLRPC"
1019*5c6c1daeSBarry Smith PetscErrorCode PetscProcessYAMLRPC(const char* request,char **result)
1020*5c6c1daeSBarry Smith {
1021*5c6c1daeSBarry Smith   yaml_parser_t  parser;
1022*5c6c1daeSBarry Smith   yaml_event_t   event;
1023*5c6c1daeSBarry Smith   int            done = 0;
1024*5c6c1daeSBarry Smith   int            count = 0;
1025*5c6c1daeSBarry Smith   size_t         len;
1026*5c6c1daeSBarry Smith   PetscErrorCode ierr;
1027*5c6c1daeSBarry Smith   PetscBool      method,params,id;
1028*5c6c1daeSBarry Smith   char           *methodname,*idname,**args,**argso = 0;
1029*5c6c1daeSBarry Smith   PetscInt       argc = 0,argco,i;
1030*5c6c1daeSBarry Smith   PetscErrorCode (*fun)(PetscInt,char **,PetscInt*,char ***);
1031*5c6c1daeSBarry Smith 
1032*5c6c1daeSBarry Smith   PetscFunctionBegin;
1033*5c6c1daeSBarry Smith   ierr = PetscMalloc(sizeof(char*),&args);CHKERRQ(ierr);
1034*5c6c1daeSBarry Smith   yaml_parser_initialize(&parser);
1035*5c6c1daeSBarry Smith   PetscStrlen(request,&len);
1036*5c6c1daeSBarry Smith   yaml_parser_set_input_string(&parser, (unsigned char *)request, len);
1037*5c6c1daeSBarry Smith 
1038*5c6c1daeSBarry Smith   /* this is totally bogus; it only handles the simple JSON-RPC messages */
1039*5c6c1daeSBarry Smith   while (!done) {
1040*5c6c1daeSBarry Smith     if (!yaml_parser_parse(&parser, &event)) {
1041*5c6c1daeSBarry Smith       ierr = PetscInfo(PETSC_NULL,"Found error in yaml/json\n");CHKERRQ(ierr);
1042*5c6c1daeSBarry Smith       break;
1043*5c6c1daeSBarry Smith     }
1044*5c6c1daeSBarry Smith     done = (event.type == YAML_STREAM_END_EVENT);
1045*5c6c1daeSBarry Smith     switch (event.type) {
1046*5c6c1daeSBarry Smith     case YAML_STREAM_START_EVENT:
1047*5c6c1daeSBarry Smith       ierr = PetscInfo(PETSC_NULL,"Stream start\n");CHKERRQ(ierr);
1048*5c6c1daeSBarry Smith       break;
1049*5c6c1daeSBarry Smith     case YAML_STREAM_END_EVENT:
1050*5c6c1daeSBarry Smith       ierr = PetscInfo(PETSC_NULL,"Stream end\n");CHKERRQ(ierr);
1051*5c6c1daeSBarry Smith       break;
1052*5c6c1daeSBarry Smith     case YAML_DOCUMENT_START_EVENT:
1053*5c6c1daeSBarry Smith       ierr = PetscInfo(PETSC_NULL,"Document start\n");CHKERRQ(ierr);
1054*5c6c1daeSBarry Smith       break;
1055*5c6c1daeSBarry Smith     case YAML_DOCUMENT_END_EVENT:
1056*5c6c1daeSBarry Smith       ierr = PetscInfo(PETSC_NULL,"Document end\n");CHKERRQ(ierr);
1057*5c6c1daeSBarry Smith       break;
1058*5c6c1daeSBarry Smith     case YAML_MAPPING_START_EVENT:
1059*5c6c1daeSBarry Smith       ierr = PetscInfo(PETSC_NULL,"Mapping start event\n");CHKERRQ(ierr);
1060*5c6c1daeSBarry Smith       break;
1061*5c6c1daeSBarry Smith     case YAML_MAPPING_END_EVENT:
1062*5c6c1daeSBarry Smith       ierr = PetscInfo(PETSC_NULL,"Mapping end event \n");CHKERRQ(ierr);
1063*5c6c1daeSBarry Smith       break;
1064*5c6c1daeSBarry Smith     case YAML_ALIAS_EVENT:
1065*5c6c1daeSBarry Smith       ierr = PetscInfo1(PETSC_NULL,"Alias event %s\n",event.data.alias.anchor);CHKERRQ(ierr);
1066*5c6c1daeSBarry Smith       break;
1067*5c6c1daeSBarry Smith     case YAML_SCALAR_EVENT:
1068*5c6c1daeSBarry Smith       ierr = PetscInfo1(PETSC_NULL,"Scalar event %s\n",event.data.scalar.value);CHKERRQ(ierr);
1069*5c6c1daeSBarry Smith       ierr = PetscStrcmp((char*)event.data.scalar.value,"method",&method);CHKERRQ(ierr);
1070*5c6c1daeSBarry Smith       ierr = PetscStrcmp((char*)event.data.scalar.value,"params",&params);CHKERRQ(ierr);
1071*5c6c1daeSBarry Smith       ierr = PetscStrcmp((char*)event.data.scalar.value,"id",&id);CHKERRQ(ierr);
1072*5c6c1daeSBarry Smith       if (method) {
1073*5c6c1daeSBarry Smith         yaml_event_delete(&event);
1074*5c6c1daeSBarry Smith         ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr);
1075*5c6c1daeSBarry Smith         ierr = PetscInfo1(PETSC_NULL,"Method %s\n",event.data.scalar.value);CHKERRQ(ierr);
1076*5c6c1daeSBarry Smith         ierr = PetscStrallocpy((char*)event.data.scalar.value,&methodname);CHKERRQ(ierr);
1077*5c6c1daeSBarry Smith       } else if (id) {
1078*5c6c1daeSBarry Smith         yaml_event_delete(&event);
1079*5c6c1daeSBarry Smith         ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr);
1080*5c6c1daeSBarry Smith         ierr = PetscInfo1(PETSC_NULL,"Id %s\n",event.data.scalar.value);CHKERRQ(ierr);
1081*5c6c1daeSBarry Smith         ierr = PetscStrallocpy((char*)event.data.scalar.value,&idname);CHKERRQ(ierr);
1082*5c6c1daeSBarry Smith       } else if (params) {
1083*5c6c1daeSBarry Smith         yaml_event_delete(&event);
1084*5c6c1daeSBarry Smith         ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr);
1085*5c6c1daeSBarry Smith         yaml_event_delete(&event);
1086*5c6c1daeSBarry Smith         ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr);
1087*5c6c1daeSBarry Smith         while (event.type != YAML_SEQUENCE_END_EVENT) {
1088*5c6c1daeSBarry Smith           ierr = PetscInfo1(PETSC_NULL,"  Parameter %s\n",event.data.scalar.value);CHKERRQ(ierr);
1089*5c6c1daeSBarry Smith           ierr = PetscStrallocpy((char*)event.data.scalar.value,&args[argc++]);CHKERRQ(ierr);
1090*5c6c1daeSBarry Smith           yaml_event_delete(&event);
1091*5c6c1daeSBarry Smith           ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr);
1092*5c6c1daeSBarry Smith         }
1093*5c6c1daeSBarry Smith       } else { /* ignore all the other variables in the mapping */
1094*5c6c1daeSBarry Smith         yaml_event_delete(&event);
1095*5c6c1daeSBarry Smith         ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr);
1096*5c6c1daeSBarry Smith       }
1097*5c6c1daeSBarry Smith       break;
1098*5c6c1daeSBarry Smith     case YAML_SEQUENCE_START_EVENT:
1099*5c6c1daeSBarry Smith       ierr = PetscInfo(PETSC_NULL,"Sequence start event \n");CHKERRQ(ierr);
1100*5c6c1daeSBarry Smith       break;
1101*5c6c1daeSBarry Smith     case YAML_SEQUENCE_END_EVENT:
1102*5c6c1daeSBarry Smith       ierr = PetscInfo(PETSC_NULL,"Sequence end event \n");CHKERRQ(ierr);
1103*5c6c1daeSBarry Smith       break;
1104*5c6c1daeSBarry Smith     default:
1105*5c6c1daeSBarry Smith       /* It couldn't really happen. */
1106*5c6c1daeSBarry Smith       break;
1107*5c6c1daeSBarry Smith     }
1108*5c6c1daeSBarry Smith 
1109*5c6c1daeSBarry Smith     yaml_event_delete(&event);
1110*5c6c1daeSBarry Smith     count ++;
1111*5c6c1daeSBarry Smith   }
1112*5c6c1daeSBarry Smith   yaml_parser_delete(&parser);
1113*5c6c1daeSBarry Smith 
1114*5c6c1daeSBarry Smith   ierr = PetscDLLibrarySym(PETSC_COMM_SELF,PETSC_NULL,PETSC_NULL,methodname,(void**)&fun);CHKERRQ(ierr);
1115*5c6c1daeSBarry Smith   if (fun) {
1116*5c6c1daeSBarry Smith     ierr = PetscInfo1(PETSC_NULL,"Located function %s and running it\n",methodname);CHKERRQ(ierr);
1117*5c6c1daeSBarry Smith     ierr = (*fun)(argc,args,&argco,&argso);CHKERRQ(ierr);
1118*5c6c1daeSBarry Smith   } else {
1119*5c6c1daeSBarry Smith     ierr = PetscInfo1(PETSC_NULL,"Did not locate function %s skipping it\n",methodname);CHKERRQ(ierr);
1120*5c6c1daeSBarry Smith   }
1121*5c6c1daeSBarry Smith 
1122*5c6c1daeSBarry Smith   for (i=0; i<argc; i++) {
1123*5c6c1daeSBarry Smith     ierr = PetscFree(args[i]);CHKERRQ(ierr);
1124*5c6c1daeSBarry Smith   }
1125*5c6c1daeSBarry Smith   ierr = PetscFree(args);CHKERRQ(ierr);
1126*5c6c1daeSBarry Smith   ierr = PetscFree(methodname);CHKERRQ(ierr);
1127*5c6c1daeSBarry Smith 
1128*5c6c1daeSBarry Smith   /* convert the result back to YAML; should use YAML encoder, does not handle zero return arguments */
1129*5c6c1daeSBarry Smith   ierr = PetscMalloc(1024,result);CHKERRQ(ierr);
1130*5c6c1daeSBarry Smith   ierr = PetscStrcpy(*result,"{\"error\": null, \"id\": \"");CHKERRQ(ierr);
1131*5c6c1daeSBarry Smith   ierr = PetscStrcat(*result,idname);CHKERRQ(ierr);
1132*5c6c1daeSBarry Smith   ierr = PetscStrcat(*result,"\", \"result\" : ");CHKERRQ(ierr);
1133*5c6c1daeSBarry Smith   if (argco > 1) {ierr = PetscStrcat(*result,"[");CHKERRQ(ierr);}
1134*5c6c1daeSBarry Smith   for (i=0; i<argco; i++) {
1135*5c6c1daeSBarry Smith     ierr = PetscStrcat(*result,"\"");CHKERRQ(ierr);
1136*5c6c1daeSBarry Smith     ierr = PetscStrcat(*result,argso[i]);CHKERRQ(ierr);
1137*5c6c1daeSBarry Smith     ierr = PetscStrcat(*result,"\"");CHKERRQ(ierr);
1138*5c6c1daeSBarry Smith     if (i < argco-1) {ierr = PetscStrcat(*result,",");CHKERRQ(ierr);}
1139*5c6c1daeSBarry Smith   }
1140*5c6c1daeSBarry Smith   if (argco > 1) {ierr = PetscStrcat(*result,"]");CHKERRQ(ierr);}
1141*5c6c1daeSBarry Smith   ierr = PetscStrcat(*result,"}");CHKERRQ(ierr);
1142*5c6c1daeSBarry Smith   ierr = PetscInfo1(PETSC_NULL,"YAML result of function %s\n",*result);CHKERRQ(ierr);
1143*5c6c1daeSBarry Smith 
1144*5c6c1daeSBarry Smith   /* free work space */
1145*5c6c1daeSBarry Smith   ierr = PetscFree(idname);CHKERRQ(ierr);
1146*5c6c1daeSBarry Smith   for (i=0; i<argco; i++) {
1147*5c6c1daeSBarry Smith     ierr = PetscFree(argso[i]);CHKERRQ(ierr);
1148*5c6c1daeSBarry Smith   }
1149*5c6c1daeSBarry Smith   ierr = PetscFree(argso);CHKERRQ(ierr);
1150*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
1151*5c6c1daeSBarry Smith }
1152*5c6c1daeSBarry Smith #endif
1153*5c6c1daeSBarry Smith 
1154*5c6c1daeSBarry Smith #undef __FUNCT__
1155*5c6c1daeSBarry Smith #define __FUNCT__ "PetscWebServeRequest"
1156*5c6c1daeSBarry Smith /*@C
1157*5c6c1daeSBarry Smith       PetscWebServeRequest - serves a single web request
1158*5c6c1daeSBarry Smith 
1159*5c6c1daeSBarry Smith     Not collective
1160*5c6c1daeSBarry Smith 
1161*5c6c1daeSBarry Smith   Input Parameters:
1162*5c6c1daeSBarry Smith .   port - the port
1163*5c6c1daeSBarry Smith 
1164*5c6c1daeSBarry Smith     Level: developer
1165*5c6c1daeSBarry Smith 
1166*5c6c1daeSBarry Smith .seealso: PetscWebServe()
1167*5c6c1daeSBarry Smith @*/
1168*5c6c1daeSBarry Smith PetscErrorCode  PetscWebServeRequest(int port)
1169*5c6c1daeSBarry Smith {
1170*5c6c1daeSBarry Smith   PetscErrorCode ierr;
1171*5c6c1daeSBarry Smith   FILE           *fd,*fdo;
1172*5c6c1daeSBarry Smith   char           buf[4096],fullpath[PETSC_MAX_PATH_LEN],truefullpath[PETSC_MAX_PATH_LEN];
1173*5c6c1daeSBarry Smith   char           *method, *path, *protocol,*result;
1174*5c6c1daeSBarry Smith   const char*    type;
1175*5c6c1daeSBarry Smith   PetscBool      flg;
1176*5c6c1daeSBarry Smith   PetscToken     tok;
1177*5c6c1daeSBarry Smith   PetscInt       cnt = 8;
1178*5c6c1daeSBarry Smith 
1179*5c6c1daeSBarry Smith   PetscFunctionBegin;
1180*5c6c1daeSBarry Smith   fd = fdopen(port, "r+");
1181*5c6c1daeSBarry Smith 
1182*5c6c1daeSBarry Smith   ierr = PetscInfo(PETSC_NULL,"Processing web request\n");CHKERRQ(ierr);
1183*5c6c1daeSBarry Smith   if (!fgets(buf, sizeof(buf), fd)) {
1184*5c6c1daeSBarry Smith     ierr = PetscInfo(PETSC_NULL,"Cannot read web request, giving up\n");CHKERRQ(ierr);
1185*5c6c1daeSBarry Smith     goto theend;
1186*5c6c1daeSBarry Smith   }
1187*5c6c1daeSBarry Smith   ierr = PetscInfo1(PETSC_NULL,"Processing web request %s",buf);CHKERRQ(ierr);
1188*5c6c1daeSBarry Smith 
1189*5c6c1daeSBarry Smith   ierr = PetscTokenCreate(buf,' ',&tok);CHKERRQ(ierr);
1190*5c6c1daeSBarry Smith   ierr = PetscTokenFind(tok,&method);CHKERRQ(ierr);
1191*5c6c1daeSBarry Smith   ierr = PetscTokenFind(tok,&path);CHKERRQ(ierr);
1192*5c6c1daeSBarry Smith   ierr = PetscTokenFind(tok,&protocol);CHKERRQ(ierr);
1193*5c6c1daeSBarry Smith 
1194*5c6c1daeSBarry Smith   if (!method || !path || !protocol) {
1195*5c6c1daeSBarry Smith     ierr = PetscInfo(PETSC_NULL,"Web request not well formatted, giving up\n");CHKERRQ(ierr);
1196*5c6c1daeSBarry Smith     goto theend;
1197*5c6c1daeSBarry Smith   }
1198*5c6c1daeSBarry Smith 
1199*5c6c1daeSBarry Smith   ierr = PetscStrcmp(method,"GET",&flg);
1200*5c6c1daeSBarry Smith   if (!flg) {
1201*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_YAML)
1202*5c6c1daeSBarry Smith     ierr = PetscStrcmp(method,"POST",&flg);
1203*5c6c1daeSBarry Smith     /*
1204*5c6c1daeSBarry Smith           Start to handle support for POSTs based on json-rpc
1205*5c6c1daeSBarry Smith     */
1206*5c6c1daeSBarry Smith     if (flg) {
1207*5c6c1daeSBarry Smith       int    len;
1208*5c6c1daeSBarry Smith       size_t elen;
1209*5c6c1daeSBarry Smith       char   *fnd;
1210*5c6c1daeSBarry Smith       while (cnt--) {
1211*5c6c1daeSBarry Smith 
1212*5c6c1daeSBarry Smith         if (!fgets(buf, sizeof(buf), fd)) {
1213*5c6c1daeSBarry Smith           ierr = PetscInfo(PETSC_NULL,"Cannot read POST data, giving up\n");CHKERRQ(ierr);
1214*5c6c1daeSBarry Smith           goto theend;
1215*5c6c1daeSBarry Smith         }
1216*5c6c1daeSBarry Smith         ierr = PetscInfo1(PETSC_NULL,"POSTED data %s",buf);CHKERRQ(ierr);
1217*5c6c1daeSBarry Smith         ierr = PetscStrstr(buf,"Content-Type:",&fnd);CHKERRQ(ierr);
1218*5c6c1daeSBarry Smith         if (fnd) {
1219*5c6c1daeSBarry Smith           ierr = PetscStrstr(buf,"application/json-rpc",&fnd);CHKERRQ(ierr);
1220*5c6c1daeSBarry Smith           if (!fnd) {
1221*5c6c1daeSBarry Smith             ierr = PetscInfo(PETSC_NULL,"POST content is not json-rpc, skipping post\n");CHKERRQ(ierr);
1222*5c6c1daeSBarry Smith             goto theend;
1223*5c6c1daeSBarry Smith           }
1224*5c6c1daeSBarry Smith         }
1225*5c6c1daeSBarry Smith       }
1226*5c6c1daeSBarry Smith       if (!fgets(buf, sizeof(buf), fd)) {
1227*5c6c1daeSBarry Smith         ierr = PetscInfo(PETSC_NULL,"Cannot read POST length data, giving up\n");CHKERRQ(ierr);
1228*5c6c1daeSBarry Smith         goto theend;
1229*5c6c1daeSBarry Smith       }
1230*5c6c1daeSBarry Smith       ierr = PetscInfo1(PETSC_NULL,"POSTED length data %s",buf);CHKERRQ(ierr);
1231*5c6c1daeSBarry Smith       sscanf(buf,"Content-Length: %d\n",&len);
1232*5c6c1daeSBarry Smith       ierr = PetscInfo1(PETSC_NULL,"Length of POSTED data %d\n",len);CHKERRQ(ierr);
1233*5c6c1daeSBarry Smith       if (!fgets(buf, sizeof(buf), fd)) {
1234*5c6c1daeSBarry Smith         ierr = PetscInfo(PETSC_NULL,"Cannot read POST data, giving up\n");CHKERRQ(ierr);
1235*5c6c1daeSBarry Smith         goto theend;
1236*5c6c1daeSBarry Smith       }
1237*5c6c1daeSBarry Smith       ierr = PetscInfo1(PETSC_NULL,"POSTED data %s",buf);CHKERRQ(ierr);
1238*5c6c1daeSBarry Smith       if (!fgets(buf, sizeof(buf), fd)) {
1239*5c6c1daeSBarry Smith         ierr = PetscInfo(PETSC_NULL,"Cannot read POST data, giving up\n");CHKERRQ(ierr);
1240*5c6c1daeSBarry Smith         goto theend;
1241*5c6c1daeSBarry Smith       }
1242*5c6c1daeSBarry Smith       ierr = PetscInfo1(PETSC_NULL,"POSTED data %s",buf);CHKERRQ(ierr);
1243*5c6c1daeSBarry Smith       if (!fgets(buf, len+1, fd)) { /* why is this len + 1? */
1244*5c6c1daeSBarry Smith         ierr = PetscInfo(PETSC_NULL,"Cannot read POST data, giving up\n");CHKERRQ(ierr);
1245*5c6c1daeSBarry Smith         goto theend;
1246*5c6c1daeSBarry Smith       }
1247*5c6c1daeSBarry Smith       ierr = PetscInfo1(PETSC_NULL,"POSTED data %s\n",buf);CHKERRQ(ierr);
1248*5c6c1daeSBarry Smith       fseek(fd, 0, SEEK_CUR); /* Force change of stream direction */
1249*5c6c1daeSBarry Smith       ierr = PetscProcessYAMLRPC(buf,&result);CHKERRQ(ierr);
1250*5c6c1daeSBarry Smith       ierr = PetscStrlen(result,&elen);CHKERRQ(ierr);
1251*5c6c1daeSBarry Smith       ierr = PetscWebSendHeader(fd, 200, "OK", NULL, "application/json-rpc",(int)elen);CHKERRQ(ierr);
1252*5c6c1daeSBarry Smith       fprintf(fd, "%s",result);
1253*5c6c1daeSBarry Smith       goto theend;
1254*5c6c1daeSBarry Smith     } else {
1255*5c6c1daeSBarry Smith #endif
1256*5c6c1daeSBarry Smith       ierr = PetscWebSendError(fd, 501, "Not supported", NULL, "Method is not supported.");CHKERRQ(ierr);
1257*5c6c1daeSBarry Smith       ierr = PetscInfo(PETSC_NULL,"Web request not a GET or POST, giving up\n");CHKERRQ(ierr);
1258*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_YAML)
1259*5c6c1daeSBarry Smith     }
1260*5c6c1daeSBarry Smith #endif
1261*5c6c1daeSBarry Smith   } else {
1262*5c6c1daeSBarry Smith     fseek(fd, 0, SEEK_CUR); /* Force change of stream direction */
1263*5c6c1daeSBarry Smith 
1264*5c6c1daeSBarry Smith     ierr = PetscStrcmp(path,"/favicon.ico",&flg);CHKERRQ(ierr);
1265*5c6c1daeSBarry Smith     if (flg) {
1266*5c6c1daeSBarry Smith       /* should have cool PETSc icon */;
1267*5c6c1daeSBarry Smith       goto theend;
1268*5c6c1daeSBarry Smith     }
1269*5c6c1daeSBarry Smith     ierr = PetscStrcmp(path,"/",&flg);CHKERRQ(ierr);
1270*5c6c1daeSBarry Smith     if (flg) {
1271*5c6c1daeSBarry Smith       char        program[128];
1272*5c6c1daeSBarry Smith       PetscMPIInt size;
1273*5c6c1daeSBarry Smith       PetscViewer viewer;
1274*5c6c1daeSBarry Smith 
1275*5c6c1daeSBarry Smith       ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
1276*5c6c1daeSBarry Smith       ierr = PetscGetProgramName(program,128);CHKERRQ(ierr);
1277*5c6c1daeSBarry Smith       ierr = PetscWebSendHeader(fd, 200, "OK", NULL, "text/html", -1);CHKERRQ(ierr);
1278*5c6c1daeSBarry Smith       fprintf(fd, "<HTML><HEAD><TITLE>Petsc Application Server</TITLE></HEAD>\r\n<BODY>");
1279*5c6c1daeSBarry Smith       fprintf(fd, "<H4>Serving PETSc application code %s </H4>\r\n\n",program);
1280*5c6c1daeSBarry Smith       fprintf(fd, "Number of processes %d\r\n\n",size);
1281*5c6c1daeSBarry Smith       fprintf(fd, "<HR>\r\n");
1282*5c6c1daeSBarry Smith       ierr = PetscViewerASCIIOpenWithFILE(PETSC_COMM_WORLD,fd,&viewer);CHKERRQ(ierr);
1283*5c6c1daeSBarry Smith       ierr = PetscOptionsView(viewer);CHKERRQ(ierr);
1284*5c6c1daeSBarry Smith       ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1285*5c6c1daeSBarry Smith       fprintf(fd, "<HR>\r\n");
1286*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_AMS)
1287*5c6c1daeSBarry Smith       if (PetscAMSPublishAll) {
1288*5c6c1daeSBarry Smith 	fprintf(fd, "<a href=\"./ams-tree\">Connect to Memory Snooper--Tree Display</a></p>\r\n\r\n");
1289*5c6c1daeSBarry Smith         fprintf(fd, "<a href=\"./ams-list\">Connect to Memory Snooper--List Display</a></p>\r\n\r\n");
1290*5c6c1daeSBarry Smith       }
1291*5c6c1daeSBarry Smith #endif
1292*5c6c1daeSBarry Smith       fprintf(fd, "<a href=\"./AMSJavascript.html\">Connect to Memory Snooper--Interactive Javascript</a></p>\r\n\r\n");
1293*5c6c1daeSBarry Smith       ierr = PetscWebSendFooter(fd);CHKERRQ(ierr);
1294*5c6c1daeSBarry Smith       goto theend;
1295*5c6c1daeSBarry Smith     }
1296*5c6c1daeSBarry Smith 
1297*5c6c1daeSBarry Smith #if defined(PETSC_HAVE_AMS)
1298*5c6c1daeSBarry Smith     ierr = PetscStrcmp(path,"/ams-list",&flg);CHKERRQ(ierr);
1299*5c6c1daeSBarry Smith     if (flg) {
1300*5c6c1daeSBarry Smith       ierr = PetscAMSDisplayList(fd);CHKERRQ(ierr);
1301*5c6c1daeSBarry Smith       goto theend;
1302*5c6c1daeSBarry Smith     }
1303*5c6c1daeSBarry Smith     ierr = PetscInfo1(PETSC_NULL,"Browser path %s\n",path);
1304*5c6c1daeSBarry Smith     ierr = PetscStrcmp(path,"/ams-tree",&flg);CHKERRQ(ierr);
1305*5c6c1daeSBarry Smith     if (flg) {
1306*5c6c1daeSBarry Smith       ierr = PetscAMSDisplayTree(fd);CHKERRQ(ierr);
1307*5c6c1daeSBarry Smith       goto theend;
1308*5c6c1daeSBarry Smith     }
1309*5c6c1daeSBarry Smith #endif
1310*5c6c1daeSBarry Smith     ierr = PetscStrcpy(fullpath,"${PETSC_DIR}/include/web");CHKERRQ(ierr);
1311*5c6c1daeSBarry Smith     ierr = PetscStrcat(fullpath,path);CHKERRQ(ierr);
1312*5c6c1daeSBarry Smith     ierr = PetscInfo1(PETSC_NULL,"Checking for file %s\n",fullpath);CHKERRQ(ierr);
1313*5c6c1daeSBarry Smith     ierr = PetscStrreplace(PETSC_COMM_SELF,fullpath,truefullpath,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
1314*5c6c1daeSBarry Smith     fdo  = fopen(truefullpath,"r");
1315*5c6c1daeSBarry Smith     if (fdo) {
1316*5c6c1daeSBarry Smith       PetscInt    length,index;
1317*5c6c1daeSBarry Smith       char        data[4096];
1318*5c6c1daeSBarry Smith       struct stat statbuf;
1319*5c6c1daeSBarry Smith       int         n;
1320*5c6c1daeSBarry Smith       const char  *suffixes[] = {".html",".js",".gif",0}, *mimes[] = {"text/html","text/javascript","image/gif","text/unknown"};
1321*5c6c1daeSBarry Smith 
1322*5c6c1daeSBarry Smith       ierr = PetscStrendswithwhich(fullpath,suffixes,&index);CHKERRQ(ierr);
1323*5c6c1daeSBarry Smith       type = mimes[index];
1324*5c6c1daeSBarry Smith       if (!stat(truefullpath, &statbuf)) length = -1;
1325*5c6c1daeSBarry Smith       else length = S_ISREG(statbuf.st_mode) ? statbuf.st_size : -1;
1326*5c6c1daeSBarry Smith       ierr = PetscWebSendHeader(fd, 200, "OK", NULL, type, length);CHKERRQ(ierr);
1327*5c6c1daeSBarry Smith       while ((n = fread(data, 1, sizeof(data), fdo)) > 0) fwrite(data, 1, n, fd);
1328*5c6c1daeSBarry Smith       fclose(fdo);
1329*5c6c1daeSBarry Smith       ierr = PetscInfo2(PETSC_NULL,"Sent file %s to browser using format %s\n",fullpath,type);CHKERRQ(ierr);
1330*5c6c1daeSBarry Smith       goto theend;
1331*5c6c1daeSBarry Smith     }
1332*5c6c1daeSBarry Smith     ierr = PetscWebSendError(fd, 501, "Not supported", NULL, "Unknown request.");CHKERRQ(ierr);
1333*5c6c1daeSBarry Smith   }
1334*5c6c1daeSBarry Smith   theend:
1335*5c6c1daeSBarry Smith   ierr = PetscTokenDestroy(&tok);CHKERRQ(ierr);
1336*5c6c1daeSBarry Smith   fclose(fd);
1337*5c6c1daeSBarry Smith   ierr = PetscInfo(PETSC_NULL,"Finished processing request\n");CHKERRQ(ierr);
1338*5c6c1daeSBarry Smith 
1339*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
1340*5c6c1daeSBarry Smith }
1341*5c6c1daeSBarry Smith 
1342*5c6c1daeSBarry Smith #undef __FUNCT__
1343*5c6c1daeSBarry Smith #define __FUNCT__ "PetscWebServeWait"
1344*5c6c1daeSBarry Smith /*@C
1345*5c6c1daeSBarry Smith       PetscWebServeWait - waits for requests on a thread
1346*5c6c1daeSBarry Smith 
1347*5c6c1daeSBarry Smith     Not collective
1348*5c6c1daeSBarry Smith 
1349*5c6c1daeSBarry Smith   Input Parameter:
1350*5c6c1daeSBarry Smith .   port - port to listen on
1351*5c6c1daeSBarry Smith 
1352*5c6c1daeSBarry Smith     Level: developer
1353*5c6c1daeSBarry Smith 
1354*5c6c1daeSBarry Smith .seealso: PetscViewerSocketOpen(), PetscWebServe()
1355*5c6c1daeSBarry Smith @*/
1356*5c6c1daeSBarry Smith void  *PetscWebServeWait(int *port)
1357*5c6c1daeSBarry Smith {
1358*5c6c1daeSBarry Smith   PetscErrorCode ierr;
1359*5c6c1daeSBarry Smith   int            iport,listenport,tport = *port;
1360*5c6c1daeSBarry Smith 
1361*5c6c1daeSBarry Smith   ierr = PetscInfo1(PETSC_NULL,"Starting webserver at port %d\n",tport);if (ierr) return 0;
1362*5c6c1daeSBarry Smith   ierr = PetscFree(port);if (ierr) return 0;
1363*5c6c1daeSBarry Smith   ierr = PetscSocketEstablish(tport,&listenport);if (ierr) return 0;
1364*5c6c1daeSBarry Smith   while (1) {
1365*5c6c1daeSBarry Smith     ierr = PetscSocketListen(listenport,&iport);if (ierr) return 0;
1366*5c6c1daeSBarry Smith     ierr = PetscWebServeRequest(iport);if (ierr) return 0;
1367*5c6c1daeSBarry Smith     close(iport);
1368*5c6c1daeSBarry Smith   }
1369*5c6c1daeSBarry Smith   close(listenport);
1370*5c6c1daeSBarry Smith   return 0;
1371*5c6c1daeSBarry Smith }
1372*5c6c1daeSBarry Smith 
1373*5c6c1daeSBarry Smith #undef __FUNCT__
1374*5c6c1daeSBarry Smith #define __FUNCT__ "PetscWebServe"
1375*5c6c1daeSBarry Smith /*@C
1376*5c6c1daeSBarry Smith       PetscWebServe - start up the PETSc web server and respond to requests
1377*5c6c1daeSBarry Smith 
1378*5c6c1daeSBarry Smith     Not collective - only does something on process zero of the communicator
1379*5c6c1daeSBarry Smith 
1380*5c6c1daeSBarry Smith   Input Parameters:
1381*5c6c1daeSBarry Smith +   comm - the MPI communicator
1382*5c6c1daeSBarry Smith -   port - port to listen on
1383*5c6c1daeSBarry Smith 
1384*5c6c1daeSBarry Smith   Options Database Key:
1385*5c6c1daeSBarry Smith +  -server <port> - start PETSc webserver (default port is 8080)
1386*5c6c1daeSBarry Smith -  -ams_publish_objects
1387*5c6c1daeSBarry Smith 
1388*5c6c1daeSBarry Smith 
1389*5c6c1daeSBarry Smith    Notes: Point your browser to http://hostname:8080   to access the PETSc web server, where hostname is the name of your machine.
1390*5c6c1daeSBarry Smith       If you are running PETSc on your local machine you can use http://localhost:8080
1391*5c6c1daeSBarry Smith 
1392*5c6c1daeSBarry Smith       If the PETSc program completes before you connect with the browser you will not be able to connect to the PETSc webserver.
1393*5c6c1daeSBarry Smith 
1394*5c6c1daeSBarry Smith       Read the top of $PETSC_DIR/include/web/AMSJavascript.py before running.
1395*5c6c1daeSBarry Smith 
1396*5c6c1daeSBarry Smith     Level: developer
1397*5c6c1daeSBarry Smith 
1398*5c6c1daeSBarry Smith .seealso: PetscViewerSocketOpen()
1399*5c6c1daeSBarry Smith @*/
1400*5c6c1daeSBarry Smith PetscErrorCode  PetscWebServe(MPI_Comm comm,int port)
1401*5c6c1daeSBarry Smith {
1402*5c6c1daeSBarry Smith   PetscErrorCode ierr;
1403*5c6c1daeSBarry Smith   PetscMPIInt    rank;
1404*5c6c1daeSBarry Smith   pthread_t      thread;
1405*5c6c1daeSBarry Smith   int            *trueport;
1406*5c6c1daeSBarry Smith 
1407*5c6c1daeSBarry Smith   PetscFunctionBegin;
1408*5c6c1daeSBarry Smith   if (port < 1 && port != PETSC_DEFAULT && port != PETSC_DECIDE) SETERRQ1(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,"Cannot use negative port number %d",port);
1409*5c6c1daeSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
1410*5c6c1daeSBarry Smith   if (rank) PetscFunctionReturn(0);
1411*5c6c1daeSBarry Smith 
1412*5c6c1daeSBarry Smith   if (port == PETSC_DECIDE || port == PETSC_DEFAULT) port = 8080;
1413*5c6c1daeSBarry Smith   ierr = PetscMalloc(1*sizeof(int),&trueport);CHKERRQ(ierr); /* malloc this so it still exists in thread */
1414*5c6c1daeSBarry Smith   *trueport = port;
1415*5c6c1daeSBarry Smith   ierr = pthread_create(&thread, NULL, (void *(*)(void *))PetscWebServeWait, trueport);CHKERRQ(ierr);
1416*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
1417*5c6c1daeSBarry Smith }
1418*5c6c1daeSBarry Smith #endif
1419*5c6c1daeSBarry Smith 
1420*5c6c1daeSBarry Smith 
1421*5c6c1daeSBarry Smith 
1422*5c6c1daeSBarry Smith 
1423*5c6c1daeSBarry Smith 
1424*5c6c1daeSBarry Smith 
1425*5c6c1daeSBarry Smith 
1426*5c6c1daeSBarry Smith 
1427*5c6c1daeSBarry Smith 
1428*5c6c1daeSBarry Smith 
1429*5c6c1daeSBarry Smith 
1430*5c6c1daeSBarry Smith 
1431*5c6c1daeSBarry Smith 
1432*5c6c1daeSBarry Smith 
1433