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