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 #include <petscviewerams.h> 539 #undef __FUNCT__ 540 #define __FUNCT__ "PetscAMSObjectsDisplayList" 541 /* 542 Displays all the PETSc objects published with AMS in a simple HTML list 543 544 Does NOT use Javascript or JSON-RPC 545 */ 546 static PetscErrorCode PetscAMSObjectsDisplayList(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 ierr = PetscGetHostName(host,256);CHKERRQ(ierr); 561 ierr = AMS_Connect(host, -1, &comm_list);CHKERRQ(ierr); 562 ierr = PetscWebSendHeader(fd, 200, "OK", NULL, "text/html", -1);CHKERRQ(ierr); 563 if (!comm_list || !comm_list[0]) fprintf(fd, "AMS Communicator not running</p>\r\n"); 564 else { 565 ierr = AMS_Comm_attach(comm_list[0],&ams);CHKERRQ(ierr); 566 ierr = AMS_Comm_get_memory_list(ams,&mem_list);CHKERRQ(ierr); 567 if (!mem_list[0]) fprintf(fd, "AMS Communicator %s has no published memories</p>\r\n",comm_list[0]); 568 else { 569 fprintf(fd, "<HTML><HEAD><TITLE>Petsc Application Server</TITLE></HEAD>\r\n<BODY>"); 570 fprintf(fd,"<ul>\r\n"); 571 while (mem_list[i]) { 572 fprintf(fd,"<li> %s</li>\r\n",mem_list[i]); 573 ierr = AMS_Memory_attach(ams,mem_list[i],&memory,NULL);CHKERRQ(ierr); 574 ierr = AMS_Memory_get_field_list(memory, &fld_list);CHKERRQ(ierr); 575 j = 0; 576 fprintf(fd,"<ul>\r\n"); 577 while (fld_list[j]) { 578 fprintf(fd,"<li> %s",fld_list[j]); 579 ierr = AMS_Memory_get_field_info(memory, fld_list[j], &addr, &len, &dtype, &mtype, &stype, &rtype);CHKERRQ(ierr); 580 if (len == 1) { 581 if (dtype == AMS_INT) fprintf(fd," %d",*(int*)addr); 582 else if (dtype == AMS_STRING) fprintf(fd," %s",*(char**)addr); 583 } 584 fprintf(fd,"</li>\r\n"); 585 j++; 586 } 587 fprintf(fd,"</ul>\r\n"); 588 i++; 589 } 590 fprintf(fd,"</ul>\r\n"); 591 } 592 } 593 ierr = PetscWebSendFooter(fd);CHKERRQ(ierr); 594 ierr = AMS_Disconnect();CHKERRQ(ierr); 595 PetscFunctionReturn(0); 596 } 597 598 #undef __FUNCT__ 599 #define __FUNCT__ "PetscAMSObjectsDisplayTree" 600 /* 601 Displays all the PETSc objects published with AMS in very crude HTML 5 graphics 602 603 Does NOT use Javascript or JSON-RPC 604 */ 605 static PetscErrorCode PetscAMSObjectsDisplayTree(FILE *fd) 606 { 607 PetscErrorCode ierr; 608 char host[256],**comm_list,**mem_list,**fld_list; 609 AMS_Comm ams; 610 PetscInt i = 0,j; 611 AMS_Memory_type mtype; 612 AMS_Data_type dtype; 613 AMS_Shared_type stype; 614 AMS_Reduction_type rtype; 615 AMS_Memory memory; 616 int len; 617 void *addr2,*addr3,*addr,*addr4; 618 619 ierr = PetscGetHostName(host,256);CHKERRQ(ierr); 620 ierr = AMS_Connect(host, -1, &comm_list);CHKERRQ(ierr); 621 ierr = PetscWebSendHeader(fd, 200, "OK", NULL, "text/html", -1);CHKERRQ(ierr); 622 if (!comm_list || !comm_list[0]) fprintf(fd, "AMS Communicator not running</p>\r\n"); 623 else { 624 ierr = AMS_Comm_attach(comm_list[0],&ams);CHKERRQ(ierr); 625 ierr = AMS_Comm_get_memory_list(ams,&mem_list);CHKERRQ(ierr); 626 if (!mem_list[0]) fprintf(fd, "AMS Communicator %s has no published memories</p>\r\n",comm_list[0]); 627 else { 628 PetscInt Nlevels,*Level,*Levelcnt,*Idbylevel,*Column,*parentid,*Id,maxId = 0,maxCol = 0,*parentId,id,cnt,Nlevelcnt = 0; 629 PetscBool *mask; 630 char **classes,*clas,**subclasses,*sclas; 631 632 /* get maximum number of objects */ 633 while (mem_list[i]) { 634 ierr = AMS_Memory_attach(ams,mem_list[i],&memory,NULL);CHKERRQ(ierr); 635 ierr = AMS_Memory_get_field_list(memory, &fld_list);CHKERRQ(ierr); 636 ierr = AMS_Memory_get_field_info(memory, "Id", &addr2, &len, &dtype, &mtype, &stype, &rtype);CHKERRQ(ierr); 637 Id = (int*) addr2; 638 maxId = PetscMax(maxId,*Id); 639 i++; 640 } 641 maxId++; 642 643 /* Gets everyone's parent ID and which nodes are masked */ 644 ierr = PetscMalloc4(maxId,PetscInt,&parentid,maxId,PetscBool,&mask,maxId,char**,&classes,maxId,char**,&subclasses);CHKERRQ(ierr); 645 ierr = PetscMemzero(classes,maxId*sizeof(char*));CHKERRQ(ierr); 646 ierr = PetscMemzero(subclasses,maxId*sizeof(char*));CHKERRQ(ierr); 647 for (i=0; i<maxId; i++) mask[i] = PETSC_TRUE; 648 i = 0; 649 while (mem_list[i]) { 650 ierr = AMS_Memory_attach(ams,mem_list[i],&memory,NULL);CHKERRQ(ierr); 651 ierr = AMS_Memory_get_field_list(memory, &fld_list);CHKERRQ(ierr); 652 ierr = AMS_Memory_get_field_info(memory, "Id", &addr2, &len, &dtype, &mtype, &stype, &rtype);CHKERRQ(ierr); 653 Id = (int*) addr2; 654 ierr = AMS_Memory_get_field_info(memory, "ParentId", &addr3, &len, &dtype, &mtype, &stype, &rtype);CHKERRQ(ierr); 655 parentId = (int*) addr3; 656 ierr = AMS_Memory_get_field_info(memory, "Class", &addr, &len, &dtype, &mtype, &stype, &rtype);CHKERRQ(ierr); 657 clas = *(char**)addr; 658 ierr = AMS_Memory_get_field_info(memory, "Type", &addr4, &len, &dtype, &mtype, &stype, &rtype);CHKERRQ(ierr); 659 sclas = *(char**)addr4; 660 parentid[*Id] = *parentId; 661 mask[*Id] = PETSC_FALSE; 662 663 ierr = PetscStrallocpy(clas,classes+*Id);CHKERRQ(ierr); 664 ierr = PetscStrallocpy(sclas,subclasses+*Id);CHKERRQ(ierr); 665 i++; 666 } 667 668 /* if the parent is masked then relabel the parent as 0 since the true parent was deleted */ 669 for (i=0; i<maxId; i++) { 670 if (!mask[i] && parentid[i] > 0 && mask[parentid[i]]) parentid[i] = 0; 671 } 672 673 ierr = PetscProcessTree(maxId,mask,parentid,&Nlevels,&Level,&Levelcnt,&Idbylevel,&Column);CHKERRQ(ierr); 674 675 for (i=0; i<Nlevels; i++) maxCol = PetscMax(maxCol,Levelcnt[i]); 676 for (i=0; i<Nlevels; i++) Nlevelcnt = PetscMax(Nlevelcnt,Levelcnt[i]); 677 678 /* print all the top-level objects */ 679 fprintf(fd, "<HTML><HEAD><TITLE>Petsc Application Server</TITLE>\r\n"); 680 fprintf(fd, "<canvas width=800 height=600 id=\"tree\"></canvas>\r\n"); 681 fprintf(fd, "<script type=\"text/javascript\">\r\n"); 682 fprintf(fd, " function draw() {\r\n"); 683 fprintf(fd, " var example = document.getElementById('tree');\r\n"); 684 fprintf(fd, " var context = example.getContext('2d');\r\n"); 685 /* adjust font size based on how big a tree is printed */ 686 if (Nlevels > 5 || Nlevelcnt > 10) fprintf(fd, " context.font = \"normal 12px sans-serif\";\r\n"); 687 else fprintf(fd, " context.font = \"normal 24px sans-serif\";\r\n"); 688 fprintf(fd, " context.fillStyle = \"rgb(255,0,0)\";\r\n"); 689 fprintf(fd, " context.textBaseline = \"top\";\r\n"); 690 fprintf(fd, " var xspacep = 0;\r\n"); 691 fprintf(fd, " var yspace = example.height/%d;\r\n",(Nlevels+1)); 692 /* estimate the height of a string as twice the width of a character */ 693 fprintf(fd, " var wheight = context.measureText(\"K\");\r\n"); 694 fprintf(fd, " var height = 1.6*wheight.width;\r\n"); 695 696 cnt = 0; 697 for (i=0; i<Nlevels; i++) { 698 fprintf(fd, " var xspace = example.width/%d;\r\n",Levelcnt[i]+1); 699 for (j=0; j<Levelcnt[i]; j++) { 700 id = Idbylevel[cnt++]; 701 clas = classes[id]; 702 sclas = subclasses[id]; 703 fprintf(fd, " var width = context.measureText(\"%s\");\r\n",clas); 704 fprintf(fd, " var swidth = context.measureText(\"%s\");\r\n",sclas); 705 fprintf(fd, " context.fillStyle = \"rgb(255,0,0)\";\r\n"); 706 fprintf(fd, " context.fillRect((%d)*xspace-width.width/2, %d*yspace-height/2, width.width, height);\r\n",j+1,i+1); 707 fprintf(fd, " context.fillRect((%d)*xspace-swidth.width/2, %d*yspace+height/2, swidth.width, height);\r\n",j+1,i+1); 708 fprintf(fd, " context.fillStyle = \"rgb(0,0,0)\";\r\n"); 709 fprintf(fd, " context.fillText(\"%s\",(%d)*xspace-width.width/2, %d*yspace-height/2);\r\n",clas,j+1,i+1); 710 fprintf(fd, " context.fillText(\"%s\",(%d)*xspace-swidth.width/2, %d*yspace+height/2);\r\n",sclas,j+1,i+1); 711 if (parentid[id]) { 712 fprintf(fd, " context.moveTo(%d*xspace,%d*yspace-height/2);\r\n",j+1,i+1); 713 fprintf(fd, " context.lineTo(%d*xspacep,%d*yspace+3*height/2);\r\n",Column[parentid[id]]+1,i); 714 fprintf(fd, " context.stroke();\r\n"); 715 } 716 } 717 fprintf(fd, " xspacep = xspace;\r\n"); 718 } 719 ierr = PetscFree(Level);CHKERRQ(ierr); 720 ierr = PetscFree(Levelcnt);CHKERRQ(ierr); 721 ierr = PetscFree(Idbylevel);CHKERRQ(ierr); 722 ierr = PetscFree(Column);CHKERRQ(ierr); 723 for (i=0; i<maxId; i++) { 724 ierr = PetscFree(classes[i]);CHKERRQ(ierr); 725 ierr = PetscFree(subclasses[i]);CHKERRQ(ierr); 726 } 727 ierr = PetscFree4(mask,parentid,classes,subclasses);CHKERRQ(ierr); 728 729 ierr = AMS_Disconnect();CHKERRQ(ierr); 730 fprintf(fd, "}\r\n"); 731 fprintf(fd, "</script>\r\n"); 732 fprintf(fd, "<body onload=\"draw();\">\r\n"); 733 fprintf(fd, "</body></html>\r\n"); 734 } 735 } 736 ierr = PetscWebSendFooter(fd);CHKERRQ(ierr); 737 PetscFunctionReturn(0); 738 } 739 #endif 740 741 #undef __FUNCT__ 742 #define __FUNCT__ "PetscWebServeRequestGet" 743 /*@C 744 PetscWebServeRequestGet - serves a single web Get request 745 746 Not collective 747 748 Input Parameters: 749 + port - the network file to read and write from 750 - path - the command from the server 751 752 Level: developer 753 754 .seealso: PetscWebServe() 755 @*/ 756 static PetscErrorCode PetscWebServeRequestGet(FILE *fd,const char path[]) 757 { 758 PetscErrorCode ierr; 759 FILE *fdo; 760 char fullpath[PETSC_MAX_PATH_LEN],truefullpath[PETSC_MAX_PATH_LEN],*qmark; 761 const char *type; 762 PetscBool flg; 763 764 PetscFunctionBegin; 765 fseek(fd, 0, SEEK_CUR); /* Force change of stream direction */ 766 767 ierr = PetscStrcmp(path,"/favicon.ico",&flg);CHKERRQ(ierr); 768 if (flg) { 769 /* should have cool PETSc icon */; 770 PetscFunctionReturn(0); 771 } 772 ierr = PetscStrcmp(path,"/",&flg);CHKERRQ(ierr); 773 if (flg) { 774 char program[128]; 775 PetscMPIInt size; 776 PetscViewer viewer; 777 778 ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); 779 ierr = PetscGetProgramName(program,128);CHKERRQ(ierr); 780 ierr = PetscWebSendHeader(fd, 200, "OK", NULL, "text/html", -1);CHKERRQ(ierr); 781 fprintf(fd, "<HTML><HEAD><TITLE>Petsc Application Server</TITLE></HEAD>\r\n<BODY>"); 782 fprintf(fd, "<H4>Serving PETSc application code %s </H4>\r\n\n",program); 783 fprintf(fd, "Number of processes %d\r\n\n",size); 784 fprintf(fd, "<HR>\r\n"); 785 ierr = PetscViewerASCIIOpenWithFILE(PETSC_COMM_WORLD,fd,&viewer);CHKERRQ(ierr); 786 ierr = PetscOptionsView(viewer);CHKERRQ(ierr); 787 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 788 fprintf(fd, "<HR>\r\n"); 789 #if defined(PETSC_HAVE_AMS) 790 if (PetscAMSPublishAll) { 791 fprintf(fd, "<a href=\"./ams-tree\">Connect to Memory Snooper--Tree Display</a></p>\r\n\r\n"); 792 fprintf(fd, "<a href=\"./ams-list\">Connect to Memory Snooper--List Display</a></p>\r\n\r\n"); 793 } 794 fprintf(fd, "<a href=\"./AMSJavascript.html\">Connect to Memory Snooper--Interactive Javascript</a></p>\r\n\r\n"); 795 #endif 796 ierr = PetscWebSendFooter(fd);CHKERRQ(ierr); 797 PetscFunctionReturn(0); 798 } 799 800 #if defined(PETSC_HAVE_AMS) 801 ierr = PetscStrcmp(path,"/ams-list",&flg);CHKERRQ(ierr); 802 if (flg) { 803 ierr = PetscAMSObjectsDisplayList(fd);CHKERRQ(ierr); 804 PetscFunctionReturn(0); 805 } 806 ierr = PetscStrcmp(path,"/ams-tree",&flg);CHKERRQ(ierr); 807 if (flg) { 808 ierr = PetscAMSObjectsDisplayTree(fd);CHKERRQ(ierr); 809 PetscFunctionReturn(0); 810 } 811 #endif 812 ierr = PetscStrcpy(fullpath,"${PETSC_DIR}/include/web");CHKERRQ(ierr); 813 ierr = PetscStrcat(fullpath,path);CHKERRQ(ierr); 814 ierr = PetscInfo1(NULL,"Checking for file %s\n",fullpath);CHKERRQ(ierr); 815 ierr = PetscStrstr(fullpath,"?",&qmark);CHKERRQ(ierr); 816 if (qmark) *qmark = 0; 817 ierr = PetscStrreplace(PETSC_COMM_SELF,fullpath,truefullpath,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 818 fdo = fopen(truefullpath,"r"); 819 if (fdo) { 820 PetscInt length,index; 821 char data[4096]; 822 struct stat statbuf; 823 int n; 824 const char *suffixes[] = {".html",".js",".gif",0}, *mimes[] = {"text/html","text/javascript","image/gif","text/unknown"}; 825 826 ierr = PetscStrendswithwhich(fullpath,suffixes,&index);CHKERRQ(ierr); 827 type = mimes[index]; 828 if (!stat(truefullpath, &statbuf)) length = -1; 829 else length = S_ISREG(statbuf.st_mode) ? statbuf.st_size : -1; 830 ierr = PetscWebSendHeader(fd, 200, "OK", NULL, type, length);CHKERRQ(ierr); 831 while ((n = fread(data, 1, sizeof(data), fdo)) > 0) fwrite(data, 1, n, fd); 832 fclose(fdo); 833 ierr = PetscInfo2(NULL,"Sent file %s to browser using format %s\n",fullpath,type);CHKERRQ(ierr); 834 PetscFunctionReturn(0); 835 } 836 ierr = PetscWebSendError(fd, 501, "Not supported", NULL, "Unknown request.");CHKERRQ(ierr); 837 PetscFunctionReturn(0); 838 } 839 840 #if defined(PETSC_HAVE_YAML) 841 842 /* 843 Toy YAML/JSON-RPC function that returns all the arguments it is passed 844 */ 845 #undef __FUNCT__ 846 #define __FUNCT__ "YAML_echo" 847 PETSC_UNUSED static PetscErrorCode YAML_echo(PetscInt argc,char **args,PetscInt *argco,char ***argso) 848 { 849 PetscErrorCode ierr; 850 PetscInt i; 851 852 ierr = PetscPrintf(PETSC_COMM_SELF,"Number of arguments to function %d\n",argc);CHKERRQ(ierr); 853 for (i=0; i<argc; i++) { 854 ierr = PetscPrintf(PETSC_COMM_SELF," %s\n",args[i]);CHKERRQ(ierr); 855 } 856 *argco = argc; 857 ierr = PetscMalloc(argc*sizeof(char*),argso);CHKERRQ(ierr); 858 for (i=0; i<argc; i++) { 859 ierr = PetscStrallocpy(args[i],&(*argso)[i]);CHKERRQ(ierr); 860 } 861 PetscFunctionReturn(0); 862 } 863 864 /* ------------------------------------------------------------------------------------------- 865 The following set of functions are wrapper functions for AMS functions that 866 867 1) convert from string arguments to appropriate AMS arguments (int, double, char*, etc) 868 2) call the AMS function 869 3) convert from the AMS result arguments to string arguments 870 871 Developers Note: Rather than having PetscProcessYAMLRPC() convert the YAML/JSON representation of the params to an array of strings 872 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 873 Similarly these routines could put their result directly back into YAML/JSON rather than putting them into an array of strings 874 returning that and having PetscProcessYAMLRPC() put them into the YAML/JSON. 875 */ 876 877 #undef __FUNCT__ 878 #define __FUNCT__ "YAML_AMS_Connect" 879 /* 880 Connects to the local AMS and gets only the first communication name 881 882 Input Parameters: 883 . none 884 885 Output Parameter: 886 . oarg1 - the string name of the first communicator 887 888 */ 889 PETSC_EXTERN PetscErrorCode YAML_AMS_Connect(PetscInt argc,char **args,PetscInt *argco,char ***argso) 890 { 891 PetscErrorCode ierr; 892 char **list = 0; 893 894 PetscFunctionBegin; 895 ierr = AMS_Connect(0,-1,&list); 896 if (ierr) { 897 ierr = PetscInfo1(NULL,"AMS_Connect() error %d\n",ierr);CHKERRQ(ierr); 898 } else if (!list) { 899 ierr = PetscInfo(NULL,"AMS_Connect() list empty, not running AMS server\n");CHKERRQ(ierr); 900 } 901 *argco = 1; 902 ierr = PetscMalloc(sizeof(char*),argso);CHKERRQ(ierr); 903 if (list) { 904 ierr = PetscStrallocpy(list[0],&(*argso)[0]);CHKERRQ(ierr); 905 } else { 906 ierr = PetscStrallocpy("No AMS publisher running",&(*argso)[0]);CHKERRQ(ierr); 907 } 908 PetscFunctionReturn(0); 909 } 910 911 #undef __FUNCT__ 912 #define __FUNCT__ "YAML_AMS_Comm_attach" 913 /* 914 Attaches to an AMS communicator 915 916 Input Parameter: 917 . arg1 - string name of the communicator 918 919 Output Parameter: 920 . oarg1 - the integer name of the communicator 921 922 */ 923 PETSC_EXTERN PetscErrorCode YAML_AMS_Comm_attach(PetscInt argc,char **args,PetscInt *argco,char ***argso) 924 { 925 PetscErrorCode ierr; 926 AMS_Comm comm = -1; 927 928 PetscFunctionBegin; 929 ierr = AMS_Comm_attach(args[0],&comm); 930 if (ierr) {ierr = PetscInfo1(NULL,"AMS_Comm_attach() error %d\n",ierr);CHKERRQ(ierr);} 931 *argco = 1; 932 ierr = PetscMalloc(sizeof(char*),argso);CHKERRQ(ierr); 933 ierr = PetscMalloc(3*sizeof(char*),&argso[0][0]);CHKERRQ(ierr); 934 sprintf(argso[0][0],"%d",(int)comm); 935 PetscFunctionReturn(0); 936 } 937 938 #undef __FUNCT__ 939 #define __FUNCT__ "YAML_AMS_Comm_get_memory_list" 940 /* 941 Gets the list of memories on an AMS Comm 942 943 Input Parameter: 944 . arg1 - integer name of the communicator 945 946 Output Parameter: 947 . oarg1 - the list of names 948 949 */ 950 PETSC_EXTERN PetscErrorCode YAML_AMS_Comm_get_memory_list(PetscInt argc,char **args,PetscInt *argco,char ***argso) 951 { 952 PetscErrorCode ierr; 953 char **mem_list; 954 AMS_Comm comm; 955 PetscInt i,iargco = 0; 956 957 PetscFunctionBegin; 958 sscanf(args[0],"%d",&comm); 959 ierr = AMS_Comm_get_memory_list(comm,&mem_list); 960 if (ierr) { 961 ierr = PetscInfo1(NULL,"AMS_Comm_get_memory_list() error %d\n",ierr);CHKERRQ(ierr); 962 } else { 963 while (mem_list[iargco++]) ; 964 iargco--; 965 966 ierr = PetscMalloc((iargco)*sizeof(char*),argso);CHKERRQ(ierr); 967 for (i=0; i<iargco; i++) { 968 ierr = PetscStrallocpy(mem_list[i],(*argso)+i);CHKERRQ(ierr); 969 } 970 } 971 *argco = iargco; 972 PetscFunctionReturn(0); 973 } 974 975 #undef __FUNCT__ 976 #define __FUNCT__ "YAML_AMS_Memory_attach" 977 /* 978 Attaches to an AMS memory in a communicator 979 980 Input Parameter: 981 . arg1 - communicator 982 . arg2 - string name of the memory 983 984 Output Parameter: 985 . oarg1 - the integer name of the memory 986 . oarg2 - the integer step of the memory 987 988 */ 989 PETSC_EXTERN PetscErrorCode YAML_AMS_Memory_attach(PetscInt argc,char **args,PetscInt *argco,char ***argso) 990 { 991 PetscErrorCode ierr; 992 AMS_Comm comm; 993 AMS_Memory mem; 994 unsigned int step; 995 996 PetscFunctionBegin; 997 sscanf(args[0],"%d",&comm); 998 ierr = AMS_Memory_attach(comm,args[1],&mem,&step); 999 if (ierr) {ierr = PetscInfo1(NULL,"AMS_Memory_attach() error %d\n",ierr);CHKERRQ(ierr);} 1000 *argco = 2; 1001 ierr = PetscMalloc(2*sizeof(char*),argso);CHKERRQ(ierr); 1002 ierr = PetscMalloc(3*sizeof(char*),&argso[0][0]);CHKERRQ(ierr); 1003 sprintf(argso[0][0],"%d",(int)mem); 1004 ierr = PetscMalloc(3*sizeof(char*),&argso[0][1]);CHKERRQ(ierr); 1005 sprintf(argso[0][1],"%d",(int)step); 1006 PetscFunctionReturn(0); 1007 } 1008 1009 #undef __FUNCT__ 1010 #define __FUNCT__ "YAML_AMS_Memory_get_field_list" 1011 /* 1012 Gets the list of fields on an AMS Memory 1013 1014 Input Parameter: 1015 . arg1 - integer name of the memory 1016 1017 Output Parameter: 1018 . oarg1 - the list of names 1019 1020 */ 1021 PETSC_EXTERN PetscErrorCode YAML_AMS_Memory_get_field_list(PetscInt argc,char **args,PetscInt *argco,char ***argso) 1022 { 1023 PetscErrorCode ierr; 1024 char **field_list; 1025 AMS_Memory mem; 1026 PetscInt i,iargco = 0; 1027 1028 PetscFunctionBegin; 1029 sscanf(args[0],"%d",&mem); 1030 ierr = AMS_Memory_get_field_list(mem,&field_list); 1031 if (ierr) { 1032 ierr = PetscInfo1(NULL,"AMS_Memory_get_field_list() error %d\n",ierr);CHKERRQ(ierr); 1033 } else { 1034 while (field_list[iargco++]) ; 1035 iargco--; 1036 1037 ierr = PetscMalloc((iargco)*sizeof(char*),argso);CHKERRQ(ierr); 1038 for (i=0; i<iargco; i++) { 1039 ierr = PetscStrallocpy(field_list[i],(*argso)+i);CHKERRQ(ierr); 1040 } 1041 } 1042 *argco = iargco; 1043 PetscFunctionReturn(0); 1044 } 1045 1046 const char *AMS_Data_types[] = {"AMS_DATA_UNDEF","AMS_BOOLEAN","AMS_INT","AMS_FLOAT","AMS_DOUBLE","AMS_STRING","AMS_Data_type","AMS_",0}; 1047 const char *AMS_Memory_types[] = {"AMS_MEMORY_UNDEF","AMS_READ","AMS_WRITE","AMS_Memory_type","AMS_",0}; 1048 const char *AMS_Shared_types[] = {"AMS_SHARED_UNDEF","AMS_COMMON","AMS_REDUCED","AMS_DISTRIBUTED","AMS_Shared_type","AMS_",0}; 1049 const char *AMS_Reduction_types[] = {"AMS_REDUCTION_WHY_NOT_UNDEF?","AMS_SUM","AMS_MAX","AMS_MIN","AMS_REDUCTION_UNDEF","AMS_Reduction_type","AMS_",0}; 1050 1051 #undef __FUNCT__ 1052 #define __FUNCT__ "YAML_AMS_Utility_ArrayToString" 1053 static PetscErrorCode YAML_AMS_Utility_ArrayToString(PetscInt n,void *addr,AMS_Data_type dtype,char **result) 1054 { 1055 PetscErrorCode ierr; 1056 1057 PetscFunctionBegin; 1058 if (n == 1) { 1059 if (dtype == AMS_STRING) { 1060 ierr = PetscStrallocpy(*(const char**)addr,result);CHKERRQ(ierr); 1061 } else if (dtype == AMS_DOUBLE) { 1062 ierr = PetscMalloc(20*sizeof(char),result);CHKERRQ(ierr); 1063 sprintf(*result,"%18.16e",*(double*)addr); 1064 } else if (dtype == AMS_INT) { 1065 ierr = PetscMalloc(10*sizeof(char),result);CHKERRQ(ierr); 1066 sprintf(*result,"%d",*(int*)addr); 1067 } else if (dtype == AMS_BOOLEAN) { 1068 if (*(PetscBool*)addr) { 1069 ierr = PetscStrallocpy("true",result);CHKERRQ(ierr); 1070 } else { 1071 ierr = PetscStrallocpy("false",result);CHKERRQ(ierr); 1072 } 1073 } else { 1074 ierr = PetscStrallocpy("Not yet done",result);CHKERRQ(ierr); 1075 } 1076 } else { 1077 PetscInt i; 1078 size_t len = 0,lent; 1079 char buff[25],**array = (char**)addr; 1080 1081 if (dtype == AMS_STRING) { 1082 for (i=0; i<n; i++) { 1083 ierr = PetscStrlen(array[i],&lent);CHKERRQ(ierr); 1084 len += lent + 3; 1085 } 1086 ierr = PetscMalloc(len*sizeof(char),result);CHKERRQ(ierr); 1087 ierr = PetscStrcpy(*result,"[\"");CHKERRQ(ierr); 1088 for (i=0; i<n-1; i++) { 1089 ierr = PetscStrcat(*result,array[i]);CHKERRQ(ierr); 1090 ierr = PetscStrcat(*result,"\",\"");CHKERRQ(ierr); 1091 } 1092 ierr = PetscStrcat(*result,array[n-1]);CHKERRQ(ierr); 1093 ierr = PetscStrcat(*result,"\"]");CHKERRQ(ierr); 1094 } else if (dtype == AMS_DOUBLE) { 1095 ierr = PetscMalloc(30*n*sizeof(char),result);CHKERRQ(ierr); 1096 ierr = PetscStrcpy(*result,"[\"");CHKERRQ(ierr); 1097 for (i=0; i<n-1; i++) { 1098 sprintf(buff,"%18.16e",*(double*)addr); 1099 ierr = PetscStrcat(*result,buff);CHKERRQ(ierr); 1100 ierr = PetscStrcat(*result,"\",\"");CHKERRQ(ierr); 1101 addr = (void *) ((char *)addr + sizeof(PetscReal)); 1102 } 1103 sprintf(buff,"%18.16e",*(double*)addr); 1104 ierr = PetscStrcat(*result,buff);CHKERRQ(ierr); 1105 ierr = PetscStrcat(*result,"\"]");CHKERRQ(ierr); 1106 } else if (dtype == AMS_INT) { 1107 ierr = PetscMalloc(13*n*sizeof(char),result);CHKERRQ(ierr); 1108 ierr = PetscStrcpy(*result,"[\"");CHKERRQ(ierr); 1109 for (i=0; i<n-1; i++) { 1110 sprintf(buff,"%d",*(int*)addr); 1111 ierr = PetscStrcat(*result,buff);CHKERRQ(ierr); 1112 ierr = PetscStrcat(*result,"\",\"");CHKERRQ(ierr); 1113 addr = (void *) ((char *)addr + sizeof(PetscInt)); 1114 } 1115 sprintf(buff,"%d",*(int*)addr); 1116 ierr = PetscStrcat(*result,buff);CHKERRQ(ierr); 1117 ierr = PetscStrcat(*result,"\"]");CHKERRQ(ierr); 1118 } else if (dtype == AMS_BOOLEAN) { 1119 ierr = PetscMalloc(7*n*sizeof(char),result);CHKERRQ(ierr); 1120 ierr = PetscStrcpy(*result,"[\"");CHKERRQ(ierr); 1121 for (i=0; i<n-1; i++) { 1122 ierr = PetscStrcat(*result,*(PetscBool*)addr ? "true" : "false");CHKERRQ(ierr); 1123 addr = (void *) ((char *)addr + sizeof(int)); 1124 } 1125 ierr = PetscStrcat(*result,*(PetscBool*)addr ? "true" : "false");CHKERRQ(ierr); 1126 ierr = PetscStrcat(*result,"\"]");CHKERRQ(ierr); 1127 } else { 1128 ierr = PetscStrallocpy("Not yet done",result);CHKERRQ(ierr); 1129 } 1130 } 1131 PetscFunctionReturn(0); 1132 } 1133 1134 #undef __FUNCT__ 1135 #define __FUNCT__ "YAML_AMS_Memory_get_field_info" 1136 /* 1137 Gets information about a field 1138 1139 Input Parameter: 1140 . arg1 - memory 1141 . arg2 - string name of the field 1142 1143 Output Parameter: 1144 1145 */ 1146 PETSC_EXTERN PetscErrorCode YAML_AMS_Memory_get_field_info(PetscInt argc,char **args,PetscInt *argco,char ***argso) 1147 { 1148 PetscErrorCode ierr; 1149 AMS_Memory mem; 1150 char *addr; 1151 int len; 1152 AMS_Data_type dtype; 1153 AMS_Memory_type mtype; 1154 AMS_Shared_type stype; 1155 AMS_Reduction_type rtype; 1156 1157 PetscFunctionBegin; 1158 sscanf(args[0],"%d",&mem); 1159 ierr = AMS_Memory_get_field_info(mem,args[1],(void*)&addr,&len,&dtype,&mtype,&stype,&rtype); 1160 if (ierr) {ierr = PetscInfo1(NULL,"AMS_Memory_get_field_info() error %d\n",ierr);CHKERRQ(ierr);} 1161 *argco = 5; 1162 ierr = PetscMalloc((*argco)*sizeof(char*),argso);CHKERRQ(ierr); 1163 ierr = PetscStrallocpy(AMS_Data_types[dtype],&argso[0][0]);CHKERRQ(ierr); 1164 ierr = PetscStrallocpy(AMS_Memory_types[mtype],&argso[0][1]);CHKERRQ(ierr); 1165 ierr = PetscStrallocpy(AMS_Shared_types[stype],&argso[0][2]);CHKERRQ(ierr); 1166 ierr = PetscStrallocpy(AMS_Reduction_types[rtype],&argso[0][3]);CHKERRQ(ierr); 1167 ierr = YAML_AMS_Utility_ArrayToString(len,addr,dtype,&argso[0][4]);CHKERRQ(ierr); 1168 PetscFunctionReturn(0); 1169 } 1170 1171 #include "yaml.h" 1172 #undef __FUNCT__ 1173 #define __FUNCT__ "PetscProcessYAMLRPC" 1174 /* 1175 1) Parses a YAML/JSON-RPC function call generating a function name for an AMS wrapper function and the arguments to the function 1176 2) loads the function with dlsym(), 1177 3) calls the wrapper function with the arguments 1178 4) converts the result arguments back to YAML/JSON. 1179 */ 1180 static PetscErrorCode PetscProcessYAMLRPC(const char *request,char **result) 1181 { 1182 yaml_parser_t parser; 1183 yaml_event_t event; 1184 int done = 0; 1185 int count = 0; 1186 size_t len; 1187 PetscErrorCode ierr; 1188 PetscBool method,params,id; 1189 char *methodname,*idname,**args,**argso = 0; 1190 PetscInt argc = 0,argco,i; 1191 PetscErrorCode (*fun)(PetscInt,char**,PetscInt*,char***); 1192 1193 PetscFunctionBegin; 1194 ierr = PetscMalloc(sizeof(char*),&args);CHKERRQ(ierr); 1195 yaml_parser_initialize(&parser); 1196 PetscStrlen(request,&len); 1197 yaml_parser_set_input_string(&parser, (unsigned char*)request, len); 1198 1199 /* this is totally bogus; it only handles the simple JSON-RPC messages */ 1200 while (!done) { 1201 if (!yaml_parser_parse(&parser, &event)) { 1202 ierr = PetscInfo(NULL,"Found error in yaml/json\n");CHKERRQ(ierr); 1203 break; 1204 } 1205 done = (event.type == YAML_STREAM_END_EVENT); 1206 switch (event.type) { 1207 case YAML_STREAM_START_EVENT: 1208 ierr = PetscInfo(NULL,"Stream start\n");CHKERRQ(ierr); 1209 break; 1210 case YAML_STREAM_END_EVENT: 1211 ierr = PetscInfo(NULL,"Stream end\n");CHKERRQ(ierr); 1212 break; 1213 case YAML_DOCUMENT_START_EVENT: 1214 ierr = PetscInfo(NULL,"Document start\n");CHKERRQ(ierr); 1215 break; 1216 case YAML_DOCUMENT_END_EVENT: 1217 ierr = PetscInfo(NULL,"Document end\n");CHKERRQ(ierr); 1218 break; 1219 case YAML_MAPPING_START_EVENT: 1220 ierr = PetscInfo(NULL,"Mapping start event\n");CHKERRQ(ierr); 1221 break; 1222 case YAML_MAPPING_END_EVENT: 1223 ierr = PetscInfo(NULL,"Mapping end event \n");CHKERRQ(ierr); 1224 break; 1225 case YAML_ALIAS_EVENT: 1226 ierr = PetscInfo1(NULL,"Alias event %s\n",event.data.alias.anchor);CHKERRQ(ierr); 1227 break; 1228 case YAML_SCALAR_EVENT: 1229 ierr = PetscInfo1(NULL,"Scalar event %s\n",event.data.scalar.value);CHKERRQ(ierr); 1230 ierr = PetscStrcmp((char*)event.data.scalar.value,"method",&method);CHKERRQ(ierr); 1231 ierr = PetscStrcmp((char*)event.data.scalar.value,"params",¶ms);CHKERRQ(ierr); 1232 ierr = PetscStrcmp((char*)event.data.scalar.value,"id",&id);CHKERRQ(ierr); 1233 if (method) { 1234 yaml_event_delete(&event); 1235 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1236 ierr = PetscInfo1(NULL,"Method %s\n",event.data.scalar.value);CHKERRQ(ierr); 1237 ierr = PetscStrallocpy((char*)event.data.scalar.value,&methodname);CHKERRQ(ierr); 1238 } else if (id) { 1239 yaml_event_delete(&event); 1240 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1241 ierr = PetscInfo1(NULL,"Id %s\n",event.data.scalar.value);CHKERRQ(ierr); 1242 ierr = PetscStrallocpy((char*)event.data.scalar.value,&idname);CHKERRQ(ierr); 1243 } else if (params) { 1244 yaml_event_delete(&event); 1245 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1246 yaml_event_delete(&event); 1247 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1248 while (event.type != YAML_SEQUENCE_END_EVENT) { 1249 ierr = PetscInfo1(NULL," Parameter %s\n",event.data.scalar.value);CHKERRQ(ierr); 1250 ierr = PetscStrallocpy((char*)event.data.scalar.value,&args[argc++]);CHKERRQ(ierr); 1251 yaml_event_delete(&event); 1252 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1253 } 1254 } else { /* ignore all the other variables in the mapping */ 1255 yaml_event_delete(&event); 1256 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1257 } 1258 break; 1259 case YAML_SEQUENCE_START_EVENT: 1260 ierr = PetscInfo(NULL,"Sequence start event \n");CHKERRQ(ierr); 1261 break; 1262 case YAML_SEQUENCE_END_EVENT: 1263 ierr = PetscInfo(NULL,"Sequence end event \n");CHKERRQ(ierr); 1264 break; 1265 default: 1266 /* It couldn't really happen. */ 1267 break; 1268 } 1269 1270 yaml_event_delete(&event); 1271 count++; 1272 } 1273 yaml_parser_delete(&parser); 1274 1275 ierr = PetscDLLibrarySym(PETSC_COMM_SELF,NULL,NULL,methodname,(void**)&fun);CHKERRQ(ierr); 1276 if (fun) { 1277 ierr = PetscInfo1(NULL,"Located function %s and running it\n",methodname);CHKERRQ(ierr); 1278 ierr = (*fun)(argc,args,&argco,&argso);CHKERRQ(ierr); 1279 } else { 1280 ierr = PetscInfo1(NULL,"Did not locate function %s skipping it\n",methodname);CHKERRQ(ierr); 1281 } 1282 1283 for (i=0; i<argc; i++) { 1284 ierr = PetscFree(args[i]);CHKERRQ(ierr); 1285 } 1286 ierr = PetscFree(args);CHKERRQ(ierr); 1287 ierr = PetscFree(methodname);CHKERRQ(ierr); 1288 1289 /* convert the result back to YAML/JSON; should use YAML/JSON encoder, does not handle zero return arguments */ 1290 ierr = PetscMalloc(16000,result);CHKERRQ(ierr); 1291 ierr = PetscStrcpy(*result,"{\"error\": null, \"id\": \"");CHKERRQ(ierr); 1292 ierr = PetscStrcat(*result,idname);CHKERRQ(ierr); 1293 ierr = PetscStrcat(*result,"\", \"result\" : ");CHKERRQ(ierr); 1294 if (argco > 1) {ierr = PetscStrcat(*result,"[");CHKERRQ(ierr);} 1295 for (i=0; i<argco; i++) { 1296 if (argso[i][0] != '[') { 1297 ierr = PetscStrcat(*result,"\"");CHKERRQ(ierr); 1298 } 1299 ierr = PetscStrcat(*result,argso[i]);CHKERRQ(ierr); 1300 if (argso[i][0] != '[') { 1301 ierr = PetscStrcat(*result,"\"");CHKERRQ(ierr); 1302 } 1303 if (i < argco-1) {ierr = PetscStrcat(*result,",");CHKERRQ(ierr);} 1304 } 1305 if (argco > 1) {ierr = PetscStrcat(*result,"]");CHKERRQ(ierr);} 1306 ierr = PetscStrcat(*result,"}");CHKERRQ(ierr); 1307 ierr = PetscInfo1(NULL,"YAML/JSON result of function %s\n",*result);CHKERRQ(ierr); 1308 1309 /* free work space */ 1310 ierr = PetscFree(idname);CHKERRQ(ierr); 1311 for (i=0; i<argco; i++) { 1312 ierr = PetscFree(argso[i]);CHKERRQ(ierr); 1313 } 1314 ierr = PetscFree(argso);CHKERRQ(ierr); 1315 PetscFunctionReturn(0); 1316 } 1317 1318 #undef __FUNCT__ 1319 #define __FUNCT__ "PetscWebServeRequestPostAMSJSONRPC" 1320 /*@C 1321 PetscWebServeRequestPostAMSJSONRPC - serves a single web POST request based on JSON-RPC 1322 1323 This function allows a Javascript program (running in the browser) to make an AMS function 1324 call via JSON-RPC 1325 1326 The currently available Javascript programs are in ${PETSC_DIR}/include/web 1327 1328 Not collective 1329 1330 Input Parameters: 1331 . fd - the network file to read and write from 1332 - path - the command from the server 1333 1334 Level: developer 1335 1336 .seealso: PetscWebServe() 1337 @*/ 1338 static PetscErrorCode PetscWebServeRequestPostAMSJSONRPC(FILE *fd,const char path[]) 1339 { 1340 PetscErrorCode ierr; 1341 char buf[16000]; 1342 char *result; 1343 int len = -1; 1344 size_t elen; 1345 char *fnd; 1346 1347 PetscFunctionBegin; 1348 while (PETSC_TRUE) { 1349 if (!fgets(buf, sizeof(buf), fd)) { 1350 ierr = PetscInfo(NULL,"Cannot read POST data, giving up\n");CHKERRQ(ierr); 1351 PetscFunctionReturn(0); 1352 } 1353 ierr = PetscInfo1(NULL,"POSTED header: %s",buf);CHKERRQ(ierr); 1354 ierr = PetscStrstr(buf,"Content-Type:",&fnd);CHKERRQ(ierr); 1355 if (fnd) { 1356 ierr = PetscStrstr(buf,"application/json-rpc",&fnd);CHKERRQ(ierr); 1357 if (!fnd) { 1358 ierr = PetscInfo(NULL,"POSTED content is not json-rpc, skipping post\n");CHKERRQ(ierr); 1359 PetscFunctionReturn(0); 1360 } 1361 } 1362 ierr = PetscStrstr(buf,"Content-Length:",&fnd);CHKERRQ(ierr); 1363 if (fnd) { 1364 sscanf(buf,"Content-Length: %d\n",&len); 1365 ierr = PetscInfo1(NULL,"POSTED Content-Length: %d\n",len);CHKERRQ(ierr); 1366 } 1367 if (buf[0] == '\r') break; 1368 } 1369 if (len == -1) { 1370 ierr = PetscInfo(NULL,"Did not find POST Content-Length in header, giving up\n");CHKERRQ(ierr); 1371 } 1372 1373 if (!fgets(buf, len+1, fd)) { /* why is this len + 1? */ 1374 ierr = PetscInfo(NULL,"Cannot read POST data, giving up\n");CHKERRQ(ierr); 1375 PetscFunctionReturn(0); 1376 } 1377 ierr = PetscInfo1(NULL,"POSTED JSON/RPC request: %s\n",buf);CHKERRQ(ierr); 1378 fseek(fd, 0, SEEK_CUR); /* Force change of stream direction */ 1379 ierr = PetscProcessYAMLRPC(buf,&result);CHKERRQ(ierr); 1380 ierr = PetscStrlen(result,&elen);CHKERRQ(ierr); 1381 ierr = PetscWebSendHeader(fd, 200, "OK", NULL, "application/json-rpc",(int)elen);CHKERRQ(ierr); 1382 fprintf(fd, "%s",result); 1383 ierr = PetscInfo(NULL,"Completed AMS JSON-RPC function call\n");CHKERRQ(ierr); 1384 PetscFunctionReturn(0); 1385 } 1386 #endif 1387 1388 #undef __FUNCT__ 1389 #define __FUNCT__ "PetscWebServeRequest" 1390 /*@C 1391 PetscWebServeRequest - serves a single web request 1392 1393 Not collective 1394 1395 Input Parameters: 1396 . port - the port 1397 1398 Level: developer 1399 1400 .seealso: PetscWebServe() 1401 @*/ 1402 static PetscErrorCode PetscWebServeRequest(int port) 1403 { 1404 PetscErrorCode ierr; 1405 FILE *fd; 1406 char buf[4096]; 1407 char *method, *path, *protocol; 1408 PetscBool flg; 1409 PetscToken tok; 1410 1411 PetscFunctionBegin; 1412 fd = fdopen(port, "r+"); 1413 1414 ierr = PetscInfo(NULL,"Processing web request\n");CHKERRQ(ierr); 1415 if (!fgets(buf, sizeof(buf), fd)) { 1416 ierr = PetscInfo(NULL,"Cannot read web request, giving up\n");CHKERRQ(ierr); 1417 goto theend; 1418 } 1419 ierr = PetscInfo1(NULL,"Processing web request %s",buf);CHKERRQ(ierr); 1420 1421 ierr = PetscTokenCreate(buf,' ',&tok);CHKERRQ(ierr); 1422 ierr = PetscTokenFind(tok,&method);CHKERRQ(ierr); 1423 ierr = PetscTokenFind(tok,&path);CHKERRQ(ierr); 1424 ierr = PetscTokenFind(tok,&protocol);CHKERRQ(ierr); 1425 1426 if (!method || !path || !protocol) { 1427 ierr = PetscInfo(NULL,"Web request not well formatted, giving up\n");CHKERRQ(ierr); 1428 goto theend; 1429 } 1430 1431 ierr = PetscStrcmp(method,"GET",&flg); 1432 if (flg) { 1433 ierr = PetscWebServeRequestGet(fd,path);CHKERRQ(ierr); 1434 } else { 1435 #if defined(PETSC_HAVE_YAML) 1436 ierr = PetscStrcmp(method,"POST",&flg); 1437 if (flg) { 1438 ierr = PetscWebServeRequestPostAMSJSONRPC(fd,path);CHKERRQ(ierr); 1439 } else { 1440 #else 1441 { 1442 #endif 1443 ierr = PetscWebSendError(fd, 501, "Not supported", NULL, "Method is not supported.");CHKERRQ(ierr); 1444 ierr = PetscInfo(NULL,"Web request not a GET or POST, giving up\n");CHKERRQ(ierr); 1445 } 1446 } 1447 theend: 1448 ierr = PetscTokenDestroy(&tok);CHKERRQ(ierr); 1449 fclose(fd); 1450 ierr = PetscInfo1(NULL,"Finished processing request %s\n",method);CHKERRQ(ierr); 1451 PetscFunctionReturn(0); 1452 } 1453 1454 #undef __FUNCT__ 1455 #define __FUNCT__ "PetscWebServeWait" 1456 /*@C 1457 PetscWebServeWait - waits for requests on a thread 1458 1459 Not collective 1460 1461 Input Parameter: 1462 . port - port to listen on 1463 1464 Level: developer 1465 1466 .seealso: PetscViewerSocketOpen(), PetscWebServe() 1467 @*/ 1468 void *PetscWebServeWait(int *port) 1469 { 1470 PetscErrorCode ierr; 1471 int iport,listenport,tport = *port; 1472 1473 ierr = PetscInfo1(NULL,"Starting webserver at port %d\n",tport);if (ierr) return 0; 1474 ierr = PetscFree(port);if (ierr) return 0; 1475 ierr = PetscSocketEstablish(tport,&listenport);if (ierr) return 0; 1476 while (1) { 1477 ierr = PetscSocketListen(listenport,&iport);if (ierr) return 0; 1478 ierr = PetscWebServeRequest(iport);if (ierr) return 0; 1479 close(iport); 1480 } 1481 close(listenport); 1482 return 0; 1483 } 1484 1485 #undef __FUNCT__ 1486 #define __FUNCT__ "PetscWebServe" 1487 /*@C 1488 PetscWebServe - start up the PETSc web server and respond to requests 1489 1490 Not collective - only does something on process zero of the communicator 1491 1492 Input Parameters: 1493 + comm - the MPI communicator 1494 - port - port to listen on 1495 1496 Options Database Key: 1497 + -server <port> - start PETSc webserver (default port is 8080) 1498 - -ams_publish_objects 1499 1500 1501 Notes: Point your browser to http://hostname:8080 to access the PETSc web server, where hostname is the name of your machine. 1502 If you are running PETSc on your local machine you can use http://localhost:8080 1503 1504 If the PETSc program completes before you connect with the browser you will not be able to connect to the PETSc webserver. 1505 1506 Read the top of $PETSC_DIR/include/web/AMSJavascript.py before running. 1507 1508 Level: intermediate 1509 1510 .seealso: PetscViewerSocketOpen() 1511 @*/ 1512 PetscErrorCode PetscWebServe(MPI_Comm comm,int port) 1513 { 1514 PetscErrorCode ierr; 1515 PetscMPIInt rank; 1516 pthread_t thread; 1517 int *trueport; 1518 1519 PetscFunctionBegin; 1520 if (port < 1 && port != PETSC_DEFAULT && port != PETSC_DECIDE) SETERRQ1(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,"Cannot use negative port number %d",port); 1521 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1522 if (rank) PetscFunctionReturn(0); 1523 1524 if (port == PETSC_DECIDE || port == PETSC_DEFAULT) port = 8080; 1525 ierr = PetscMalloc(1*sizeof(int),&trueport);CHKERRQ(ierr); /* malloc this so it still exists in thread */ 1526 *trueport = port; 1527 ierr = pthread_create(&thread, NULL, (void *(*)(void*))PetscWebServeWait, trueport);CHKERRQ(ierr); 1528 PetscFunctionReturn(0); 1529 } 1530 #endif 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545