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