Actual source code: send.c
2: #include <petscsys.h>
4: #if defined(PETSC_NEEDS_UTYPE_TYPEDEFS)
5: /* Some systems have inconsistent include files that use but do not
6: ensure that the following definitions are made */
7: typedef unsigned char u_char;
8: typedef unsigned short u_short;
9: typedef unsigned short ushort;
10: typedef unsigned int u_int;
11: typedef unsigned long u_long;
12: #endif
14: #include <errno.h>
15: #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>
51: #if defined(PETSC_NEED_CLOSE_PROTO)
53: #endif
54: #if defined(PETSC_NEED_SOCKET_PROTO)
56: #endif
57: #if defined(PETSC_NEED_SLEEP_PROTO)
59: #endif
60: #if defined(PETSC_NEED_CONNECT_PROTO)
62: #endif
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,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;
176: int optval = 1; /* Turn on the option */
179: PetscGetHostName(myname,MAXHOSTNAME);
181: PetscMemzero(&sa,sizeof(struct sockaddr_in));
183: hp = gethostbyname(myname);
184: if (!hp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Unable to get hostent information from system");
186: sa.sin_family = hp->h_addrtype;
187: sa.sin_port = htons((u_short)portnum);
189: if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error running socket() command");
190: setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&optval,sizeof(optval));
192: while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
193: #if defined(PETSC_HAVE_WSAGETLASTERROR)
194: WSAGetLastError();
195: if (ierr != WSAEADDRINUSE) {
196: #else
197: if (errno != EADDRINUSE) {
198: #endif
199: close(s);
200: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error from bind()");
201: }
202: }
203: listen(s,0);
204: *ss = s;
205: return(0);
206: }
210: /*
211: PetscSocketListens - Listens at a socket created with PetscSocketEstablish()
213: .seealso: PetscSocketEstablish()
214: */
215: PetscErrorCode PetscSocketListen(int listenport,int *t)
216: {
217: struct sockaddr_in isa;
218: #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
219: size_t i;
220: #else
221: int i;
222: #endif
225: /* wait for someone to try to connect */
226: i = sizeof(struct sockaddr_in);
227: if ((*t = accept(listenport,(struct sockaddr *)&isa,(socklen_t *)&i)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"error from accept()\n");
228: return(0);
229: }
233: /*@C
234: PetscViewerSocketOpen - Opens a connection to a MATLAB or other socket
235: based server.
237: Collective on MPI_Comm
239: Input Parameters:
240: + comm - the MPI communicator
241: . machine - the machine the server is running on,, use PETSC_NULL for the local machine, use "server" to passively wait for
242: a connection from elsewhere
243: - port - the port to connect to, use PETSC_DEFAULT for the default
245: Output Parameter:
246: . lab - a context to use when communicating with the server
248: Level: intermediate
250: Notes:
251: Most users should employ the following commands to access the
252: MATLAB PetscViewers
253: $
254: $ PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
255: $ MatView(Mat matrix,PetscViewer viewer)
256: $
257: $ or
258: $
259: $ PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
260: $ VecView(Vec vector,PetscViewer viewer)
262: Options Database Keys:
263: For use with PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
264: PETSC_VIEWER_SOCKET_() or if
265: PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
266: $ -viewer_socket_machine <machine>
267: $ -viewer_socket_port <port>
269: Environmental variables:
270: + PETSC_VIEWER_SOCKET_PORT portnumber
271: - PETSC_VIEWER_SOCKET_MACHINE machine name
273: Currently the only socket client available is MATLAB. See
274: src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.
276: Notes: The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket
277: use PetscViewerBinaryRead/Write/GetDescriptor().
279: Concepts: MATLAB^sending data
280: Concepts: sockets^sending data
282: .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
283: PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD,
284: PETSC_VIEWER_SOCKET_SELF, PetscViewerBinaryWrite(), PetscViewerBinaryRead(), PetscViewerBinaryWriteStringArray(),
285: PetscBinaryViewerGetDescriptor()
286: @*/
287: PetscErrorCode PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
288: {
292: PetscViewerCreate(comm,lab);
293: PetscViewerSetType(*lab,PETSCVIEWERSOCKET);
294: PetscViewerSocketSetConnection(*lab,machine,port);
295: return(0);
296: }
300: PetscErrorCode PetscViewerSetFromOptions_Socket(PetscViewer v)
301: {
303: PetscInt def = -1;
304: char sdef[256];
305: PetscBool tflg;
308: /*
309: These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
310: are listed here for the GUI to display
311: */
312: PetscOptionsHead("Socket PetscViewer Options");
313: PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);
314: if (tflg) {
315: PetscOptionsStringToInt(sdef,&def);
316: } else {
317: def = PETSCSOCKETDEFAULTPORT;
318: }
319: PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);
321: PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);
322: PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);
323: if (!tflg) {
324: PetscGetHostName(sdef,256);
325: }
326: PetscOptionsTail();
327: return(0);
328: }
333: PetscErrorCode PetscViewerCreate_Socket(PetscViewer v)
334: {
335: PetscViewer_Socket *vmatlab;
336: PetscErrorCode ierr;
339: PetscNewLog(v,PetscViewer_Socket,&vmatlab);
340: vmatlab->port = 0;
341: v->data = (void*)vmatlab;
342: v->ops->destroy = PetscViewerDestroy_Socket;
343: v->ops->flush = 0;
344: v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;
346: /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */
347: PetscObjectChangeTypeName((PetscObject)v,PETSCVIEWERBINARY);
348: return(0);
349: }
354: /*@C
355: PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket
356: viewer is to use
358: Logically Collective on PetscViewer
360: Input Parameters:
361: + v - viewer to connect
362: . machine - host to connect to, use PETSC_NULL for the local machine,use "server" to passively wait for
363: a connection from elsewhere
364: - port - the port on the machine one is connecting to, use PETSC_DEFAULT for default
366: Level: advanced
368: .seealso: PetscViewerSocketOpen()
369: @*/
370: PetscErrorCode PetscViewerSocketSetConnection(PetscViewer v,const char machine[],int port)
371: {
372: PetscErrorCode ierr;
373: PetscMPIInt rank;
374: char mach[256];
375: PetscBool tflg;
376: PetscViewer_Socket *vmatlab = (PetscViewer_Socket *)v->data;
380: if (port <= 0) {
381: char portn[16];
382: PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);
383: if (tflg) {
384: PetscInt pport;
385: PetscOptionsStringToInt(portn,&pport);
386: port = (int)pport;
387: } else {
388: port = PETSCSOCKETDEFAULTPORT;
389: }
390: }
391: if (!machine) {
392: PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);
393: if (!tflg) {
394: PetscGetHostName(mach,256);
395: }
396: } else {
397: PetscStrncpy(mach,machine,256);
398: }
400: MPI_Comm_rank(((PetscObject)v)->comm,&rank);
401: if (!rank) {
402: PetscStrcmp(mach,"server",&tflg);
403: if (tflg) {
404: int listenport;
405: PetscInfo1(v,"Waiting for connection from socket process on port %D\n",port);
406: PetscSocketEstablish(port,&listenport);
407: PetscSocketListen(listenport,&vmatlab->port);
408: close(listenport);
409: } else {
410: PetscInfo2(v,"Connecting to socket process on port %D machine %s\n",port,mach);
411: PetscOpenSocket(mach,port,&vmatlab->port);
412: }
413: }
414: return(0);
415: }
417: /* ---------------------------------------------------------------------*/
418: /*
419: The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
420: is attached to a communicator, in this case the attribute is a PetscViewer.
421: */
422: static PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;
427: /*@C
428: PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator.
430: Collective on MPI_Comm
432: Input Parameter:
433: . comm - the MPI communicator to share the socket PetscViewer
435: Level: intermediate
437: Options Database Keys:
438: For use with the default PETSC_VIEWER_SOCKET_WORLD or if
439: PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
440: $ -viewer_socket_machine <machine>
441: $ -viewer_socket_port <port>
443: Environmental variables:
444: + PETSC_VIEWER_SOCKET_PORT portnumber
445: - PETSC_VIEWER_SOCKET_MACHINE machine name
447: Notes:
448: Unlike almost all other PETSc routines, PetscViewer_SOCKET_ does not return
449: an error code. The socket PetscViewer is usually used in the form
450: $ XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm));
452: Currently the only socket client available is MATLAB. See
453: src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.
455: Connects to a waiting socket and stays connected until PetscViewerDestroy() is called.
457: Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for communicating with the MATLAB engine.
459: .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
460: PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(),
461: PetscViewerBinaryWriteStringArray(), PetscBinaryViewerGetDescriptor(), PETSC_VIEWER_MATLAB_()
462: @*/
463: PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm)
464: {
466: PetscBool flg;
467: PetscViewer viewer;
468: MPI_Comm ncomm;
471: 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);}
472: if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) {
473: MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0);
474: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
475: }
476: MPI_Attr_get(ncomm,Petsc_Viewer_Socket_keyval,(void **)&viewer,(int*)&flg);
477: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
478: if (!flg) { /* PetscViewer not yet created */
479: PetscViewerSocketOpen(ncomm,0,0,&viewer);
480: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
481: PetscObjectRegisterDestroy((PetscObject)viewer);
482: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
483: MPI_Attr_put(ncomm,Petsc_Viewer_Socket_keyval,(void*)viewer);
484: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
485: }
486: PetscCommDestroy(&ncomm);
487: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
488: PetscFunctionReturn(viewer);
489: }
491: #if defined(PETSC_USE_SERVER)
493: #include <pthread.h>
494: #include <time.h>
495: #define PROTOCOL "HTTP/1.1"
496: #define RFC1123FMT "%a, %d %b %Y %H:%M:%S GMT"
500: PetscErrorCode PetscWebSendHeader(FILE *f, int status, const char *title, const char *extra, const char *mime, int length)
501: {
502: time_t now;
503: char timebuf[128];
506: fprintf(f, "%s %d %s\r\n", PROTOCOL, status, title);
507: fprintf(f, "Server: %s\r\n", "petscserver/1.0");
508: now = time(NULL);
509: strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&now));
510: fprintf(f, "Date: %s\r\n", timebuf);
511: if (extra) fprintf(f, "%s\r\n", extra);
512: if (mime) fprintf(f, "Content-Type: %s\r\n", mime);
513: if (length >= 0) fprintf(f, "Content-Length: %d\r\n", length);
514: fprintf(f, "Connection: close\r\n");
515: fprintf(f, "\r\n");
516: return(0);
517: }
521: PetscErrorCode PetscWebSendFooter(FILE *fd)
522: {
524: fprintf(fd, "</BODY></HTML>\r\n");
525: return(0);
526: }
530: PetscErrorCode PetscWebSendError(FILE *f, int status, const char *title, const char *extra, const char *text)
531: {
535: PetscWebSendHeader(f, status, title, extra, "text/html", -1);
536: fprintf(f, "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\r\n", status, title);
537: fprintf(f, "<BODY><H4>%d %s</H4>\r\n", status, title);
538: fprintf(f, "%s\r\n", text);
539: PetscWebSendFooter(f);
540: return(0);
541: }
543: #if defined(PETSC_HAVE_AMS)
546: PetscErrorCode PetscAMSDisplayList(FILE *fd)
547: {
548: PetscErrorCode ierr;
549: char host[256],**comm_list,**mem_list,**fld_list;
550: AMS_Comm ams;
551: PetscInt i = 0,j;
552: AMS_Memory_type mtype;
553: AMS_Data_type dtype;
554: AMS_Shared_type stype;
555: AMS_Reduction_type rtype;
556: AMS_Memory memory;
557: int len;
558: void *addr;
559:
560: PetscGetHostName(host,256);
561: AMS_Connect(host, -1, &comm_list);
562: PetscWebSendHeader(fd, 200, "OK", NULL, "text/html", -1);
563: if (!comm_list || !comm_list[0]) {
564: fprintf(fd, "AMS Communicator not running</p>\r\n");
565: } else {
566: AMS_Comm_attach(comm_list[0],&ams);
567: AMS_Comm_get_memory_list(ams,&mem_list);
568: if (!mem_list[0]) {
569: fprintf(fd, "AMS Communicator %s has no published memories</p>\r\n",comm_list[0]);
570: } else {
571: fprintf(fd, "<HTML><HEAD><TITLE>Petsc Application Server</TITLE></HEAD>\r\n<BODY>");
572: fprintf(fd,"<ul>\r\n");
573: while (mem_list[i]) {
574: fprintf(fd,"<li> %s</li>\r\n",mem_list[i]);
575: AMS_Memory_attach(ams,mem_list[i],&memory,NULL);
576: AMS_Memory_get_field_list(memory, &fld_list);
577: j = 0;
578: fprintf(fd,"<ul>\r\n");
579: while (fld_list[j]) {
580: fprintf(fd,"<li> %s",fld_list[j]);
581: AMS_Memory_get_field_info(memory, fld_list[j], &addr, &len, &dtype, &mtype, &stype, &rtype);
582: if (len == 1) {
583: if (dtype == AMS_INT) fprintf(fd," %d",*(int*)addr);
584: else if (dtype == AMS_STRING) fprintf(fd," %s",*(char**)addr);
585: }
586: fprintf(fd,"</li>\r\n");
587: j++;
588: }
589: fprintf(fd,"</ul>\r\n");
590: i++;
591: }
592: fprintf(fd,"</ul>\r\n");
593: }
594: }
595: PetscWebSendFooter(fd);
596: AMS_Disconnect();
597: return(0);
598: }
602: PetscErrorCode PetscAMSDisplayTree(FILE *fd)
603: {
604: PetscErrorCode ierr;
605: char host[256],**comm_list,**mem_list,**fld_list;
606: AMS_Comm ams;
607: PetscInt i = 0,j;
608: AMS_Memory_type mtype;
609: AMS_Data_type dtype;
610: AMS_Shared_type stype;
611: AMS_Reduction_type rtype;
612: AMS_Memory memory;
613: int len;
614: void *addr2,*addr3,*addr,*addr4;
615:
616: PetscGetHostName(host,256);
617: AMS_Connect(host, -1, &comm_list);
618: PetscWebSendHeader(fd, 200, "OK", NULL, "text/html", -1);
619: if (!comm_list || !comm_list[0]) {
620: fprintf(fd, "AMS Communicator not running</p>\r\n");
621: } else {
622: AMS_Comm_attach(comm_list[0],&ams);
623: AMS_Comm_get_memory_list(ams,&mem_list);
624: if (!mem_list[0]) {
625: fprintf(fd, "AMS Communicator %s has no published memories</p>\r\n",comm_list[0]);
626: } else {
627: PetscInt Nlevels,*Level,*Levelcnt,*Idbylevel,*Column,*parentid,*Id,maxId = 0,maxCol = 0,*parentId,id,cnt,Nlevelcnt = 0;
628: PetscBool *mask;
629: char **classes,*clas,**subclasses,*sclas;
631: /* get maximum number of objects */
632: while (mem_list[i]) {
633: AMS_Memory_attach(ams,mem_list[i],&memory,NULL);
634: AMS_Memory_get_field_list(memory, &fld_list);
635: AMS_Memory_get_field_info(memory, "Id", &addr2, &len, &dtype, &mtype, &stype, &rtype);
636: Id = (int*) addr2;
637: maxId = PetscMax(maxId,*Id);
638: i++;
639: }
640: maxId++;
642: /* Gets everyone's parent ID and which nodes are masked */
643: PetscMalloc4(maxId,PetscInt,&parentid,maxId,PetscBool ,&mask,maxId,char**,&classes,maxId,char**,&subclasses);
644: PetscMemzero(classes,maxId*sizeof(char*));
645: PetscMemzero(subclasses,maxId*sizeof(char*));
646: for (i=0; i<maxId; i++) mask[i] = PETSC_TRUE;
647: i = 0;
648: while (mem_list[i]) {
649: AMS_Memory_attach(ams,mem_list[i],&memory,NULL);
650: AMS_Memory_get_field_list(memory, &fld_list);
651: AMS_Memory_get_field_info(memory, "Id", &addr2, &len, &dtype, &mtype, &stype, &rtype);
652: Id = (int*) addr2;
653: AMS_Memory_get_field_info(memory, "ParentId", &addr3, &len, &dtype, &mtype, &stype, &rtype);
654: parentId = (int*) addr3;
655: AMS_Memory_get_field_info(memory, "Class", &addr, &len, &dtype, &mtype, &stype, &rtype);
656: clas = *(char**)addr;
657: AMS_Memory_get_field_info(memory, "Type", &addr4, &len, &dtype, &mtype, &stype, &rtype);
658: sclas = *(char**)addr4;
659: parentid[*Id] = *parentId;
660: mask[*Id] = PETSC_FALSE;
661: PetscStrallocpy(clas,classes+*Id);
662: PetscStrallocpy(sclas,subclasses+*Id);
663: i++;
664: }
666: /* if the parent is masked then relabel the parent as 0 since the true parent was deleted */
667: for (i=0; i<maxId; i++) {
668: if (!mask[i] && parentid[i] > 0 && mask[parentid[i]]) parentid[i] = 0;
669: }
671: PetscProcessTree(maxId,mask,parentid,&Nlevels,&Level,&Levelcnt,&Idbylevel,&Column);
673: for (i=0; i<Nlevels; i++) {
674: maxCol = PetscMax(maxCol,Levelcnt[i]);
675: }
676: for (i=0; i<Nlevels; i++) {
677: Nlevelcnt = PetscMax(Nlevelcnt,Levelcnt[i]);
678: }
680: /* print all the top-level objects */
681: fprintf(fd, "<HTML><HEAD><TITLE>Petsc Application Server</TITLE>\r\n");
682: fprintf(fd, "<canvas width=800 height=600 id=\"tree\"></canvas>\r\n");
683: fprintf(fd, "<script type=\"text/javascript\">\r\n");
684: fprintf(fd, " function draw(){\r\n");
685: fprintf(fd, " var example = document.getElementById('tree');\r\n");
686: fprintf(fd, " var context = example.getContext('2d');\r\n");
687: /* adjust font size based on how big a tree is printed */
688: if (Nlevels > 5 || Nlevelcnt > 10) {
689: fprintf(fd, " context.font = \"normal 12px sans-serif\";\r\n");
690: } else {
691: fprintf(fd, " context.font = \"normal 24px sans-serif\";\r\n");
692: }
693: fprintf(fd, " context.fillStyle = \"rgb(255,0,0)\";\r\n");
694: fprintf(fd, " context.textBaseline = \"top\";\r\n");
695: fprintf(fd, " var xspacep = 0;\r\n");
696: fprintf(fd, " var yspace = example.height/%d;\r\n",(Nlevels+1));
697: /* estimate the height of a string as twice the width of a character */
698: fprintf(fd, " var wheight = context.measureText(\"K\");\r\n");
699: fprintf(fd, " var height = 1.6*wheight.width;\r\n");
701: cnt = 0;
702: for (i=0; i<Nlevels; i++) {
703: fprintf(fd, " var xspace = example.width/%d;\r\n",Levelcnt[i]+1);
704: for (j=0; j<Levelcnt[i]; j++) {
705: id = Idbylevel[cnt++];
706: clas = classes[id];
707: sclas = subclasses[id];
708: fprintf(fd, " var width = context.measureText(\"%s\");\r\n",clas);
709: fprintf(fd, " var swidth = context.measureText(\"%s\");\r\n",sclas);
710: fprintf(fd, " context.fillStyle = \"rgb(255,0,0)\";\r\n");
711: fprintf(fd, " context.fillRect((%d)*xspace-width.width/2, %d*yspace-height/2, width.width, height);\r\n",j+1,i+1);
712: fprintf(fd, " context.fillRect((%d)*xspace-swidth.width/2, %d*yspace+height/2, swidth.width, height);\r\n",j+1,i+1);
713: fprintf(fd, " context.fillStyle = \"rgb(0,0,0)\";\r\n");
714: fprintf(fd, " context.fillText(\"%s\",(%d)*xspace-width.width/2, %d*yspace-height/2);\r\n",clas,j+1,i+1);
715: fprintf(fd, " context.fillText(\"%s\",(%d)*xspace-swidth.width/2, %d*yspace+height/2);\r\n",sclas,j+1,i+1);
716: if (parentid[id]) {
717: fprintf(fd, " context.moveTo(%d*xspace,%d*yspace-height/2);\r\n",j+1,i+1);
718: fprintf(fd, " context.lineTo(%d*xspacep,%d*yspace+3*height/2);\r\n",Column[parentid[id]]+1,i);
719: fprintf(fd, " context.stroke();\r\n");
720: }
721: }
722: fprintf(fd, " xspacep = xspace;\r\n");
723: }
724: PetscFree(Level);
725: PetscFree(Levelcnt);
726: PetscFree(Idbylevel);
727: PetscFree(Column);
728: for (i=0; i<maxId; i++) {
729: PetscFree(classes[i]);
730: PetscFree(subclasses[i]);
731: }
732: PetscFree4(mask,parentid,classes,subclasses);
734: AMS_Disconnect();
735: fprintf(fd, "}\r\n");
736: fprintf(fd, "</script>\r\n");
737: fprintf(fd, "<body onload=\"draw();\">\r\n");
738: fprintf(fd, "</body></html>\r\n");
739: }
740: }
741: PetscWebSendFooter(fd);
743: return(0);
744: }
745: #endif
747: #if defined(PETSC_HAVE_YAML)
750: /*
751: Toy function that returns all the arguments it is passed
752: */
755: PetscErrorCode YAML_echo(PetscInt argc,char **args,PetscInt *argco,char ***argso)
756: {
758: PetscInt i;
760: PetscPrintf(PETSC_COMM_SELF,"Number of arguments to function %d\n",argc);
761: for (i=0; i<argc; i++) {
762: PetscPrintf(PETSC_COMM_SELF," %s\n",args[i]);
763: }
764: *argco = argc;
765: PetscMalloc(argc*sizeof(char*),argso);
766: for (i=0; i<argc; i++) {
767: PetscStrallocpy(args[i],&(*argso)[i]);
768: }
769: return(0);
770: }
776: /*
777: Connects to the local AMS and gets only the first communication name
779: Input Parameters:
780: . none
782: Output Parameter:
783: . oarg1 - the string name of the first communicator
785: */
786: PetscErrorCode YAML_AMS_Connect(PetscInt argc,char **args,PetscInt *argco,char ***argso)
787: {
789: char **list = 0;
792: AMS_Connect(0,-1,&list);
793: if (ierr) {PetscInfo1(PETSC_NULL,"AMS_Connect() error %d\n",ierr);}
794: else if (!list) {PetscInfo(PETSC_NULL,"AMS_Connect() list empty, not running AMS server\n");}
795: *argco = 1;
796: PetscMalloc(sizeof(char*),argso);
797: if (list){
798: PetscStrallocpy(list[0],&(*argso)[0]);
799: } else {
800: PetscStrallocpy("No AMS publisher running",&(*argso)[0]);
801: }
802: return(0);
803: }
809: /*
810: Attaches to an AMS communicator
812: Input Parameter:
813: . arg1 - string name of the communicator
815: Output Parameter:
816: . oarg1 - the integer name of the communicator
818: */
819: PetscErrorCode YAML_AMS_Comm_attach(PetscInt argc,char **args,PetscInt *argco,char ***argso)
820: {
822: AMS_Comm comm = -1;
825: AMS_Comm_attach(args[0],&comm);
826: if (ierr) {PetscInfo1(PETSC_NULL,"AMS_Comm_attach() error %d\n",ierr);}
827: *argco = 1;
828: PetscMalloc(sizeof(char*),argso);
829: PetscMalloc(3*sizeof(char*),&argso[0][0]);
830: sprintf(argso[0][0],"%d",(int)comm);
831: return(0);
832: }
838: /*
839: Gets the list of memories on an AMS Comm
841: Input Parameter:
842: . arg1 - integer name of the communicator
844: Output Parameter:
845: . oarg1 - the list of names
847: */
848: PetscErrorCode YAML_AMS_Comm_get_memory_list(PetscInt argc,char **args,PetscInt *argco,char ***argso)
849: {
851: char **mem_list;
852: AMS_Comm comm;
853: PetscInt i,iargco = 0;
856: sscanf(args[0],"%d",&comm);
857: AMS_Comm_get_memory_list(comm,&mem_list);
858: if (ierr) {
859: PetscInfo1(PETSC_NULL,"AMS_Comm_get_memory_list() error %d\n",ierr);
860: } else {
861: while (mem_list[iargco++]) ;
862: iargco--;
864: PetscMalloc((iargco)*sizeof(char*),argso);
865: for (i=0; i<iargco; i++) {
866: PetscStrallocpy(mem_list[i],(*argso)+i);
867: }
868: }
869: *argco = iargco;
870: return(0);
871: }
877: /*
878: Attaches to an AMS memory in a communicator
880: Input Parameter:
881: . arg1 - communicator
882: . arg2 - string name of the memory
884: Output Parameter:
885: . oarg1 - the integer name of the memory
886: . oarg2 - the integer step of the memory
888: */
889: PetscErrorCode YAML_AMS_Memory_attach(PetscInt argc,char **args,PetscInt *argco,char ***argso)
890: {
892: AMS_Comm comm;
893: AMS_Memory mem;
894: unsigned int step;
897: sscanf(args[0],"%d",&comm);
898: AMS_Memory_attach(comm,args[1],&mem,&step);
899: if (ierr) {PetscInfo1(PETSC_NULL,"AMS_Memory_attach() error %d\n",ierr);}
900: *argco = 2;
901: PetscMalloc(2*sizeof(char*),argso);
902: PetscMalloc(3*sizeof(char*),&argso[0][0]);
903: sprintf(argso[0][0],"%d",(int)mem);
904: PetscMalloc(3*sizeof(char*),&argso[0][1]);
905: sprintf(argso[0][1],"%d",(int)step);
906: return(0);
907: }
913: /*
914: Gets the list of fields on an AMS Memory
916: Input Parameter:
917: . arg1 - integer name of the memory
919: Output Parameter:
920: . oarg1 - the list of names
922: */
923: PetscErrorCode YAML_AMS_Memory_get_field_list(PetscInt argc,char **args,PetscInt *argco,char ***argso)
924: {
926: char **field_list;
927: AMS_Memory mem;
928: PetscInt i,iargco = 0;
931: sscanf(args[0],"%d",&mem);
932: AMS_Memory_get_field_list(mem,&field_list);
933: if (ierr) {
934: PetscInfo1(PETSC_NULL,"AMS_Memory_get_field_list() error %d\n",ierr);
935: } else {
936: while (field_list[iargco++]) ;
937: iargco--;
939: PetscMalloc((iargco)*sizeof(char*),argso);
940: for (i=0; i<iargco; i++) {
941: PetscStrallocpy(field_list[i],(*argso)+i);
942: }
943: }
944: *argco = iargco;
945: return(0);
946: }
949: const char *AMS_Data_types[] = {"AMS_DATA_UNDEF","AMS_BOOLEAN","AMS_INT","AMS_FLOAT","AMS_DOUBLE","AMS_STRING","AMS_Data_type","AMS_",0};
950: const char *AMS_Memory_types[] = {"AMS_MEMORY_UNDEF","AMS_READ","AMS_WRITE","AMS_Memory_type","AMS_",0};
951: const char *AMS_Shared_types[] = {"AMS_SHARED_UNDEF","AMS_COMMON","AMS_REDUCED","AMS_DISTRIBUTED","AMS_Shared_type","AMS_",0};
952: 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: /*
958: Gets information about a field
960: Input Parameter:
961: . arg1 - memory
962: . arg2 - string name of the field
964: Output Parameter:
966: */
967: PetscErrorCode YAML_AMS_Memory_get_field_info(PetscInt argc,char **args,PetscInt *argco,char ***argso)
968: {
969: PetscErrorCode ierr;
970: AMS_Memory mem;
971: void *addr;
972: int len;
973: AMS_Data_type dtype;
974: AMS_Memory_type mtype;
975: AMS_Shared_type stype;
976: AMS_Reduction_type rtype;
977: PetscInt i;
980: sscanf(args[0],"%d",&mem);
981: AMS_Memory_get_field_info(mem,args[1],&addr,&len,&dtype,&mtype,&stype,&rtype);
982: if (ierr) {PetscInfo1(PETSC_NULL,"AMS_Memory_get_field_info() error %d\n",ierr);}
983: *argco = 4 + len;
984: PetscMalloc((*argco)*sizeof(char*),argso);
985: PetscStrallocpy(AMS_Data_types[dtype],&argso[0][0]);
986: PetscStrallocpy(AMS_Memory_types[mtype],&argso[0][1]);
987: PetscStrallocpy(AMS_Shared_types[stype],&argso[0][2]);
988: PetscStrallocpy(AMS_Reduction_types[rtype],&argso[0][3]);
989: for (i=0; i<len; i++) {
990: if (dtype == AMS_STRING) {
991: PetscStrallocpy(*(const char **)addr,&argso[0][4+i]);
992: } else if (dtype == AMS_DOUBLE) {
993: PetscMalloc(20*sizeof(char),&argso[0][4+i]);
994: sprintf(argso[0][4+i],"%18.16e",*(double*)addr);
995: } else if (dtype == AMS_INT) {
996: PetscMalloc(10*sizeof(char),&argso[0][4+i]);
997: sprintf(argso[0][4+i],"%d",*(int*)addr);
998: } else if (dtype == AMS_BOOLEAN) {
999: if (*(int*)addr) {
1000: PetscStrallocpy("true",&argso[0][4+i]);
1001: } else {
1002: PetscStrallocpy("false",&argso[0][4+i]);
1003: }
1004: } else {
1005: PetscStrallocpy("Not yet done",&argso[0][4+i]);
1006: }
1007: }
1008: return(0);
1009: }
1012: #include "yaml.h"
1015: PetscErrorCode PetscProcessYAMLRPC(const char* request,char **result)
1016: {
1017: yaml_parser_t parser;
1018: yaml_event_t event;
1019: int done = 0;
1020: int count = 0;
1021: size_t len;
1023: PetscBool method,params,id;
1024: char *methodname,*idname,**args,**argso = 0;
1025: PetscInt argc = 0,argco,i;
1026: PetscErrorCode (*fun)(PetscInt,char **,PetscInt*,char ***);
1029: PetscMalloc(sizeof(char*),&args);
1030: yaml_parser_initialize(&parser);
1031: PetscStrlen(request,&len);
1032: yaml_parser_set_input_string(&parser, (unsigned char *)request, len);
1034: /* this is totally bogus; it only handles the simple JSON-RPC messages */
1035: while (!done) {
1036: if (!yaml_parser_parse(&parser, &event)) {
1037: PetscInfo(PETSC_NULL,"Found error in yaml/json\n");
1038: break;
1039: }
1040: done = (event.type == YAML_STREAM_END_EVENT);
1041: switch (event.type) {
1042: case YAML_STREAM_START_EVENT:
1043: PetscInfo(PETSC_NULL,"Stream start\n");
1044: break;
1045: case YAML_STREAM_END_EVENT:
1046: PetscInfo(PETSC_NULL,"Stream end\n");
1047: break;
1048: case YAML_DOCUMENT_START_EVENT:
1049: PetscInfo(PETSC_NULL,"Document start\n");
1050: break;
1051: case YAML_DOCUMENT_END_EVENT:
1052: PetscInfo(PETSC_NULL,"Document end\n");
1053: break;
1054: case YAML_MAPPING_START_EVENT:
1055: PetscInfo(PETSC_NULL,"Mapping start event\n");
1056: break;
1057: case YAML_MAPPING_END_EVENT:
1058: PetscInfo(PETSC_NULL,"Mapping end event \n");
1059: break;
1060: case YAML_ALIAS_EVENT:
1061: PetscInfo1(PETSC_NULL,"Alias event %s\n",event.data.alias.anchor);
1062: break;
1063: case YAML_SCALAR_EVENT:
1064: PetscInfo1(PETSC_NULL,"Scalar event %s\n",event.data.scalar.value);
1065: PetscStrcmp((char*)event.data.scalar.value,"method",&method);
1066: PetscStrcmp((char*)event.data.scalar.value,"params",¶ms);
1067: PetscStrcmp((char*)event.data.scalar.value,"id",&id);
1068: if (method) {
1069: yaml_event_delete(&event);
1070: yaml_parser_parse(&parser, &event);CHKERRQ(!ierr);
1071: PetscInfo1(PETSC_NULL,"Method %s\n",event.data.scalar.value);
1072: PetscStrallocpy((char*)event.data.scalar.value,&methodname);
1073: } else if (id) {
1074: yaml_event_delete(&event);
1075: yaml_parser_parse(&parser, &event);CHKERRQ(!ierr);
1076: PetscInfo1(PETSC_NULL,"Id %s\n",event.data.scalar.value);
1077: PetscStrallocpy((char*)event.data.scalar.value,&idname);
1078: } else if (params) {
1079: yaml_event_delete(&event);
1080: yaml_parser_parse(&parser, &event);CHKERRQ(!ierr);
1081: yaml_event_delete(&event);
1082: yaml_parser_parse(&parser, &event);CHKERRQ(!ierr);
1083: while (event.type != YAML_SEQUENCE_END_EVENT) {
1084: PetscInfo1(PETSC_NULL," Parameter %s\n",event.data.scalar.value);
1085: PetscStrallocpy((char*)event.data.scalar.value,&args[argc++]);
1086: yaml_event_delete(&event);
1087: yaml_parser_parse(&parser, &event);CHKERRQ(!ierr);
1088: }
1089: } else { /* ignore all the other variables in the mapping */
1090: yaml_event_delete(&event);
1091: yaml_parser_parse(&parser, &event);CHKERRQ(!ierr);
1092: }
1093: break;
1094: case YAML_SEQUENCE_START_EVENT:
1095: PetscInfo(PETSC_NULL,"Sequence start event \n");
1096: break;
1097: case YAML_SEQUENCE_END_EVENT:
1098: PetscInfo(PETSC_NULL,"Sequence end event \n");
1099: break;
1100: default:
1101: /* It couldn't really happen. */
1102: break;
1103: }
1105: yaml_event_delete(&event);
1106: count ++;
1107: }
1108: yaml_parser_delete(&parser);
1110: PetscDLLibrarySym(PETSC_COMM_SELF,PETSC_NULL,PETSC_NULL,methodname,(void**)&fun);
1111: if (fun) {
1112: PetscInfo1(PETSC_NULL,"Located function %s and running it\n",methodname);
1113: (*fun)(argc,args,&argco,&argso);
1114: } else {
1115: PetscInfo1(PETSC_NULL,"Did not locate function %s skipping it\n",methodname);
1116: }
1118: for (i=0; i<argc; i++) {
1119: PetscFree(args[i]);
1120: }
1121: PetscFree(args);
1122: PetscFree(methodname);
1124: /* convert the result back to YAML; should use YAML encoder, does not handle zero return arguments */
1125: PetscMalloc(1024,result);
1126: PetscStrcpy(*result,"{\"error\": null, \"id\": \"");
1127: PetscStrcat(*result,idname);
1128: PetscStrcat(*result,"\", \"result\" : ");
1129: if (argco > 1) {PetscStrcat(*result,"[");}
1130: for (i=0; i<argco; i++) {
1131: PetscStrcat(*result,"\"");
1132: PetscStrcat(*result,argso[i]);
1133: PetscStrcat(*result,"\"");
1134: if (i < argco-1) {PetscStrcat(*result,",");}
1135: }
1136: if (argco > 1) {PetscStrcat(*result,"]");}
1137: PetscStrcat(*result,"}");
1138: PetscInfo1(PETSC_NULL,"YAML result of function %s\n",*result);
1140: /* free work space */
1141: PetscFree(idname);
1142: for (i=0; i<argco; i++) {
1143: PetscFree(argso[i]);
1144: }
1145: PetscFree(argso);
1146: return(0);
1147: }
1148: #endif
1152: /*@C
1153: PetscWebServeRequest - serves a single web request
1155: Not collective
1157: Input Parameters:
1158: . port - the port
1160: Level: developer
1162: .seealso: PetscWebServe()
1163: @*/
1164: PetscErrorCode PetscWebServeRequest(int port)
1165: {
1167: FILE *fd,*fdo;
1168: char buf[4096],fullpath[PETSC_MAX_PATH_LEN],truefullpath[PETSC_MAX_PATH_LEN];
1169: char *method, *path, *protocol,*result;
1170: const char* type;
1171: PetscBool flg;
1172: PetscToken tok;
1173: PetscInt cnt = 8;
1176: fd = fdopen(port, "r+");
1178: PetscInfo(PETSC_NULL,"Processing web request\n");
1179: if (!fgets(buf, sizeof(buf), fd)) {
1180: PetscInfo(PETSC_NULL,"Cannot read web request, giving up\n");
1181: goto theend;
1182: }
1183: PetscInfo1(PETSC_NULL,"Processing web request %s",buf);
1185: PetscTokenCreate(buf,' ',&tok);
1186: PetscTokenFind(tok,&method);
1187: PetscTokenFind(tok,&path);
1188: PetscTokenFind(tok,&protocol);
1190: if (!method || !path || !protocol) {
1191: PetscInfo(PETSC_NULL,"Web request not well formatted, giving up\n");
1192: goto theend;
1193: }
1195: PetscStrcmp(method,"GET",&flg);
1196: if (!flg) {
1197: #if defined(PETSC_HAVE_YAML)
1198: PetscStrcmp(method,"POST",&flg);
1199: /*
1200: Start to handle support for POSTs based on json-rpc
1201: */
1202: if (flg) {
1203: int len;
1204: size_t elen;
1205: char *fnd;
1206: while (cnt--) {
1207:
1208: if (!fgets(buf, sizeof(buf), fd)) {
1209: PetscInfo(PETSC_NULL,"Cannot read POST data, giving up\n");
1210: goto theend;
1211: }
1212: PetscInfo1(PETSC_NULL,"POSTED data %s",buf);
1213: PetscStrstr(buf,"Content-Type:",&fnd);
1214: if (fnd) {
1215: PetscStrstr(buf,"application/json-rpc",&fnd);
1216: if (!fnd) {
1217: PetscInfo(PETSC_NULL,"POST content is not json-rpc, skipping post\n");
1218: goto theend;
1219: }
1220: }
1221: }
1222: if (!fgets(buf, sizeof(buf), fd)) {
1223: PetscInfo(PETSC_NULL,"Cannot read POST length data, giving up\n");
1224: goto theend;
1225: }
1226: PetscInfo1(PETSC_NULL,"POSTED length data %s",buf);
1227: sscanf(buf,"Content-Length: %d\n",&len);
1228: PetscInfo1(PETSC_NULL,"Length of POSTED data %d\n",len);
1229: if (!fgets(buf, sizeof(buf), fd)) {
1230: PetscInfo(PETSC_NULL,"Cannot read POST data, giving up\n");
1231: goto theend;
1232: }
1233: PetscInfo1(PETSC_NULL,"POSTED data %s",buf);
1234: if (!fgets(buf, sizeof(buf), fd)) {
1235: PetscInfo(PETSC_NULL,"Cannot read POST data, giving up\n");
1236: goto theend;
1237: }
1238: PetscInfo1(PETSC_NULL,"POSTED data %s",buf);
1239: if (!fgets(buf, len+1, fd)) { /* why is this len + 1? */
1240: PetscInfo(PETSC_NULL,"Cannot read POST data, giving up\n");
1241: goto theend;
1242: }
1243: PetscInfo1(PETSC_NULL,"POSTED data %s\n",buf);
1244: fseek(fd, 0, SEEK_CUR); /* Force change of stream direction */
1245: PetscProcessYAMLRPC(buf,&result);
1246: PetscStrlen(result,&elen);
1247: PetscWebSendHeader(fd, 200, "OK", NULL, "application/json-rpc",(int)elen);
1248: fprintf(fd, "%s",result);
1249: goto theend;
1250: } else {
1251: #endif
1252: PetscWebSendError(fd, 501, "Not supported", NULL, "Method is not supported.");
1253: PetscInfo(PETSC_NULL,"Web request not a GET or POST, giving up\n");
1254: #if defined(PETSC_HAVE_YAML)
1255: }
1256: #endif
1257: } else {
1258: fseek(fd, 0, SEEK_CUR); /* Force change of stream direction */
1260: PetscStrcmp(path,"/favicon.ico",&flg);
1261: if (flg) {
1262: /* should have cool PETSc icon */;
1263: goto theend;
1264: }
1265: PetscStrcmp(path,"/",&flg);
1266: if (flg) {
1267: char program[128];
1268: PetscMPIInt size;
1269: PetscViewer viewer;
1271: MPI_Comm_size(PETSC_COMM_WORLD,&size);
1272: PetscGetProgramName(program,128);
1273: PetscWebSendHeader(fd, 200, "OK", NULL, "text/html", -1);
1274: fprintf(fd, "<HTML><HEAD><TITLE>Petsc Application Server</TITLE></HEAD>\r\n<BODY>");
1275: fprintf(fd, "<H4>Serving PETSc application code %s </H4>\r\n\n",program);
1276: fprintf(fd, "Number of processes %d\r\n\n",size);
1277: fprintf(fd, "<HR>\r\n");
1278: PetscViewerASCIIOpenWithFILE(PETSC_COMM_WORLD,fd,&viewer);
1279: PetscOptionsView(viewer);
1280: PetscViewerDestroy(&viewer);
1281: fprintf(fd, "<HR>\r\n");
1282: #if defined(PETSC_HAVE_AMS)
1283: if (PetscAMSPublishAll) {
1284: fprintf(fd, "<a href=\"./ams-tree\">Connect to Memory Snooper--Tree Display</a></p>\r\n\r\n");
1285: fprintf(fd, "<a href=\"./ams-list\">Connect to Memory Snooper--List Display</a></p>\r\n\r\n");
1286: }
1287: #endif
1288: fprintf(fd, "<a href=\"./AMSJavascript.html\">Connect to Memory Snooper--Interactive Javascript</a></p>\r\n\r\n");
1289: PetscWebSendFooter(fd);
1290: goto theend;
1291: }
1293: #if defined(PETSC_HAVE_AMS)
1294: PetscStrcmp(path,"/ams-list",&flg);
1295: if (flg) {
1296: PetscAMSDisplayList(fd);
1297: goto theend;
1298: }
1299: printf("path %s\n",path);
1300: PetscStrcmp(path,"/ams-tree",&flg);
1301: if (flg) {
1302: printf("found path %s\n",path);
1303: PetscAMSDisplayTree(fd);
1304: goto theend;
1305: }
1306: #endif
1307: PetscStrcpy(fullpath,"${PETSC_DIR}/include/web");
1308: PetscStrcat(fullpath,path);
1309: PetscInfo1(PETSC_NULL,"Checking for file %s\n",fullpath);
1310: PetscStrreplace(PETSC_COMM_SELF,fullpath,truefullpath,PETSC_MAX_PATH_LEN);
1311: fdo = fopen(truefullpath,"r");
1312: if (fdo) {
1313: PetscInt length,index;
1314: char data[4096];
1315: struct stat statbuf;
1316: int n;
1317: const char *suffixes[] = {".html",".js",".gif",0}, *mimes[] = {"text/html","text/javascript","image/gif","text/unknown"};
1319: PetscStrendswithwhich(fullpath,suffixes,&index);
1320: type = mimes[index];
1321: if (!stat(truefullpath, &statbuf)) length = -1;
1322: else length = S_ISREG(statbuf.st_mode) ? statbuf.st_size : -1;
1323: PetscWebSendHeader(fd, 200, "OK", NULL, type, length);
1324: while ((n = fread(data, 1, sizeof(data), fdo)) > 0) fwrite(data, 1, n, fd);
1325: fclose(fdo);
1326: PetscInfo2(PETSC_NULL,"Sent file %s to browser using format %s\n",fullpath,type);
1327: goto theend;
1328: }
1329: PetscWebSendError(fd, 501, "Not supported", NULL, "Unknown request.");
1330: }
1331: theend:
1332: PetscTokenDestroy(tok);
1333: fclose(fd);
1334: PetscInfo(PETSC_NULL,"Finished processing request\n");
1336: return(0);
1337: }
1341: /*@C
1342: PetscWebServeWait - waits for requests on a thread
1344: Not collective
1346: Input Parameter:
1347: . port - port to listen on
1349: Level: developer
1351: .seealso: PetscViewerSocketOpen()
1352: @*/
1353: void *PetscWebServeWait(int *port)
1354: {
1356: int iport,listenport,tport = *port;
1358: PetscInfo1(PETSC_NULL,"Starting webserver at port %d\n",tport);if (ierr) return 0;
1359: PetscFree(port);if (ierr) return 0;
1360: PetscSocketEstablish(tport,&listenport);if (ierr) return 0;
1361: while (1) {
1362: PetscSocketListen(listenport,&iport);if (ierr) return 0;
1363: PetscWebServeRequest(iport);if (ierr) return 0;
1364: close(iport);
1365: }
1366: close(listenport);
1367: return 0;
1368: }
1372: /*@C
1373: PetscWebServe - start up the PETSc web server and respond to requests
1375: Not collective - only does something on process zero of the communicator
1377: Input Parameters:
1378: + comm - the MPI communicator
1379: - port - port to listen on
1381: Options Database Key:
1382: . -server <port> - start PETSc webserver (default port is 8080)
1384: Notes: Point your browser to http://hostname:8080 to access the PETSc web server, where hostname is the name of your machine.
1385: If you are running PETSc on your local machine you can use http://localhost:8080
1387: If the PETSc program completes before you connect with the browser you will not be able to connect to the PETSc webserver.
1389: Level: developer
1391: .seealso: PetscViewerSocketOpen()
1392: @*/
1393: PetscErrorCode PetscWebServe(MPI_Comm comm,int port)
1394: {
1396: PetscMPIInt rank;
1397: pthread_t thread;
1398: int *trueport;
1401: if (port < 1 && port != PETSC_DEFAULT && port != PETSC_DECIDE) SETERRQ1(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,"Cannot use negative port number %d",port);
1402: MPI_Comm_rank(comm,&rank);
1403: if (rank) return(0);
1405: if (port == PETSC_DECIDE || port == PETSC_DEFAULT) port = 8080;
1406: PetscMalloc(1*sizeof(int),&trueport); /* malloc this so it still exists in thread */
1407: *trueport = port;
1408: pthread_create(&thread, NULL, (void *(*)(void *))PetscWebServeWait, trueport);
1409: return(0);
1410: }
1411: #endif