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 PetscStackCallAMS(AMS_Connect,(host, -1, &comm_list)); 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 PetscStackCallAMS(AMS_Comm_attach,(comm_list[0],&ams)); 566 PetscStackCallAMS(AMS_Comm_get_memory_list,(ams,&mem_list)); 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 PetscStackCallAMS(AMS_Memory_attach,(ams,mem_list[i],&memory,NULL)); 574 PetscStackCallAMS(AMS_Memory_get_field_list,(memory, &fld_list)); 575 j = 0; 576 fprintf(fd,"<ul>\r\n"); 577 while (fld_list[j]) { 578 fprintf(fd,"<li> %s",fld_list[j]); 579 PetscStackCallAMS(AMS_Memory_get_field_info,(memory, fld_list[j], &addr, &len, &dtype, &mtype, &stype, &rtype)); 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 PetscStackCallAMS(AMS_Disconnect,()); 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 PetscStackCallAMS(AMS_Connect,(host, -1, &comm_list)); 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 PetscStackCallAMS(AMS_Comm_attach,(comm_list[0],&ams)); 625 PetscStackCallAMS(AMS_Comm_get_memory_list,(ams,&mem_list)); 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 PetscStackCallAMS(AMS_Memory_attach,(ams,mem_list[i],&memory,NULL)); 635 PetscStackCallAMS(AMS_Memory_get_field_list,(memory, &fld_list)); 636 PetscStackCallAMS(AMS_Memory_get_field_info,(memory, "Id", &addr2, &len, &dtype, &mtype, &stype, &rtype)); 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 PetscStackCallAMS(AMS_Memory_attach,(ams,mem_list[i],&memory,NULL)); 651 PetscStackCallAMS(AMS_Memory_get_field_list,(memory, &fld_list)); 652 PetscStackCallAMS(AMS_Memory_get_field_info,(memory, "Id", &addr2, &len, &dtype, &mtype, &stype, &rtype)); 653 Id = (int*) addr2; 654 PetscStackCallAMS(AMS_Memory_get_field_info,(memory, "ParentId", &addr3, &len, &dtype, &mtype, &stype, &rtype)); 655 parentId = (int*) addr3; 656 PetscStackCallAMS(AMS_Memory_get_field_info,(memory, "Class", &addr, &len, &dtype, &mtype, &stype, &rtype)); 657 clas = *(char**)addr; 658 PetscStackCallAMS(AMS_Memory_get_field_info,(memory, "Type", &addr4, &len, &dtype, &mtype, &stype, &rtype)); 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 PetscStackCallAMS(AMS_Disconnect,()); 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 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 fprintf(fd, "<a href=\"./AMSJavascript.html\">Connect to Memory Snooper--Interactive Javascript</a></p>\r\n\r\n"); 793 #endif 794 ierr = PetscWebSendFooter(fd);CHKERRQ(ierr); 795 PetscFunctionReturn(0); 796 } 797 798 #if defined(PETSC_HAVE_AMS) 799 ierr = PetscStrcmp(path,"/ams-list",&flg);CHKERRQ(ierr); 800 if (flg) { 801 ierr = PetscAMSObjectsDisplayList(fd);CHKERRQ(ierr); 802 PetscFunctionReturn(0); 803 } 804 ierr = PetscStrcmp(path,"/ams-tree",&flg);CHKERRQ(ierr); 805 if (flg) { 806 ierr = PetscAMSObjectsDisplayTree(fd);CHKERRQ(ierr); 807 PetscFunctionReturn(0); 808 } 809 #endif 810 ierr = PetscStrcpy(fullpath,"${PETSC_DIR}/include/web");CHKERRQ(ierr); 811 ierr = PetscStrcat(fullpath,path);CHKERRQ(ierr); 812 ierr = PetscInfo1(NULL,"Checking for file %s\n",fullpath);CHKERRQ(ierr); 813 ierr = PetscStrstr(fullpath,"?",&qmark);CHKERRQ(ierr); 814 if (qmark) *qmark = 0; 815 ierr = PetscStrreplace(PETSC_COMM_SELF,fullpath,truefullpath,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 816 fdo = fopen(truefullpath,"r"); 817 if (fdo) { 818 PetscInt length,index; 819 char data[4096]; 820 struct stat statbuf; 821 int n; 822 const char *suffixes[] = {".html",".js",".gif",0}, *mimes[] = {"text/html","text/javascript","image/gif","text/unknown"}; 823 824 ierr = PetscStrendswithwhich(fullpath,suffixes,&index);CHKERRQ(ierr); 825 type = mimes[index]; 826 if (!stat(truefullpath, &statbuf)) length = -1; 827 else length = S_ISREG(statbuf.st_mode) ? statbuf.st_size : -1; 828 ierr = PetscWebSendHeader(fd, 200, "OK", NULL, type, length);CHKERRQ(ierr); 829 while ((n = fread(data, 1, sizeof(data), fdo)) > 0) fwrite(data, 1, n, fd); 830 fclose(fdo); 831 ierr = PetscInfo2(NULL,"Sent file %s to browser using format %s\n",fullpath,type);CHKERRQ(ierr); 832 PetscFunctionReturn(0); 833 } 834 ierr = PetscWebSendError(fd, 501, "Not supported", NULL, "Unknown request.");CHKERRQ(ierr); 835 PetscFunctionReturn(0); 836 } 837 838 #if defined(PETSC_HAVE_YAML) 839 840 /* 841 Toy YAML/JSON-RPC function that returns all the arguments it is passed 842 */ 843 #undef __FUNCT__ 844 #define __FUNCT__ "YAML_echo" 845 PETSC_UNUSED static PetscErrorCode YAML_echo(PetscInt argc,char **args,PetscInt *argco,char ***argso) 846 { 847 PetscErrorCode ierr; 848 PetscInt i; 849 850 ierr = PetscPrintf(PETSC_COMM_SELF,"Number of arguments to function %d\n",argc);CHKERRQ(ierr); 851 for (i=0; i<argc; i++) { 852 ierr = PetscPrintf(PETSC_COMM_SELF," %s\n",args[i]);CHKERRQ(ierr); 853 } 854 *argco = argc; 855 ierr = PetscMalloc(argc*sizeof(char*),argso);CHKERRQ(ierr); 856 for (i=0; i<argc; i++) { 857 ierr = PetscStrallocpy(args[i],&(*argso)[i]);CHKERRQ(ierr); 858 } 859 PetscFunctionReturn(0); 860 } 861 862 /* ------------------------------------------------------------------------------------------- 863 The following set of functions are wrapper functions for AMS functions that 864 865 1) convert from string arguments to appropriate AMS arguments (int, double, char*, etc) 866 2) call the AMS function 867 3) convert from the AMS result arguments to string arguments 868 869 Developers Note: Rather than having PetscProcessYAMLRPC() convert the YAML/JSON representation of the params to an array of strings 870 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 871 Similarly these routines could put their result directly back into YAML/JSON rather than putting them into an array of strings 872 returning that and having PetscProcessYAMLRPC() put them into the YAML/JSON. 873 */ 874 875 #undef __FUNCT__ 876 #define __FUNCT__ "YAML_AMS_Utility_ArrayToString" 877 static PetscErrorCode YAML_AMS_Utility_ArrayToString(PetscInt n,void *addr,AMS_Data_type dtype,char **result) 878 { 879 PetscErrorCode ierr; 880 881 PetscFunctionBegin; 882 if (n == 1) { 883 if (dtype == AMS_STRING) { 884 ierr = PetscStrallocpy(*(const char**)addr,result);CHKERRQ(ierr); 885 } else if (dtype == AMS_DOUBLE) { 886 ierr = PetscMalloc(20*sizeof(char),result);CHKERRQ(ierr); 887 sprintf(*result,"%18.16e",*(double*)addr); 888 } else if (dtype == AMS_INT) { 889 ierr = PetscMalloc(10*sizeof(char),result);CHKERRQ(ierr); 890 sprintf(*result,"%d",*(int*)addr); 891 } else if (dtype == AMS_BOOLEAN) { 892 if (*(PetscBool*)addr) { 893 ierr = PetscStrallocpy("true",result);CHKERRQ(ierr); 894 } else { 895 ierr = PetscStrallocpy("false",result);CHKERRQ(ierr); 896 } 897 } else { 898 ierr = PetscStrallocpy("Not yet done",result);CHKERRQ(ierr); 899 } 900 } else { 901 PetscInt i; 902 size_t len = 0,lent; 903 char buff[25],**array = (char**)addr; 904 905 if (dtype == AMS_STRING) { 906 for (i=0; i<n; i++) { 907 ierr = PetscStrlen(array[i],&lent);CHKERRQ(ierr); 908 len += lent + 3; 909 } 910 ierr = PetscMalloc(len*sizeof(char),result);CHKERRQ(ierr); 911 ierr = PetscStrcpy(*result,"[\"");CHKERRQ(ierr); 912 for (i=0; i<n-1; i++) { 913 ierr = PetscStrcat(*result,array[i]);CHKERRQ(ierr); 914 ierr = PetscStrcat(*result,"\",\"");CHKERRQ(ierr); 915 } 916 ierr = PetscStrcat(*result,array[n-1]);CHKERRQ(ierr); 917 ierr = PetscStrcat(*result,"\"]");CHKERRQ(ierr); 918 } else if (dtype == AMS_DOUBLE) { 919 ierr = PetscMalloc(30*n*sizeof(char),result);CHKERRQ(ierr); 920 ierr = PetscStrcpy(*result,"[\"");CHKERRQ(ierr); 921 for (i=0; i<n-1; i++) { 922 sprintf(buff,"%18.16e",*(double*)addr); 923 ierr = PetscStrcat(*result,buff);CHKERRQ(ierr); 924 ierr = PetscStrcat(*result,"\",\"");CHKERRQ(ierr); 925 addr = (void *) ((char *)addr + sizeof(PetscReal)); 926 } 927 sprintf(buff,"%18.16e",*(double*)addr); 928 ierr = PetscStrcat(*result,buff);CHKERRQ(ierr); 929 ierr = PetscStrcat(*result,"\"]");CHKERRQ(ierr); 930 } else if (dtype == AMS_INT) { 931 ierr = PetscMalloc(13*n*sizeof(char),result);CHKERRQ(ierr); 932 ierr = PetscStrcpy(*result,"[\"");CHKERRQ(ierr); 933 for (i=0; i<n-1; i++) { 934 sprintf(buff,"%d",*(int*)addr); 935 ierr = PetscStrcat(*result,buff);CHKERRQ(ierr); 936 ierr = PetscStrcat(*result,"\",\"");CHKERRQ(ierr); 937 addr = (void *) ((char *)addr + sizeof(PetscInt)); 938 } 939 sprintf(buff,"%d",*(int*)addr); 940 ierr = PetscStrcat(*result,buff);CHKERRQ(ierr); 941 ierr = PetscStrcat(*result,"\"]");CHKERRQ(ierr); 942 } else if (dtype == AMS_BOOLEAN) { 943 ierr = PetscMalloc(7*n*sizeof(char),result);CHKERRQ(ierr); 944 ierr = PetscStrcpy(*result,"[\"");CHKERRQ(ierr); 945 for (i=0; i<n-1; i++) { 946 ierr = PetscStrcat(*result,*(PetscBool*)addr ? "true" : "false");CHKERRQ(ierr); 947 addr = (void *) ((char *)addr + sizeof(int)); 948 } 949 ierr = PetscStrcat(*result,*(PetscBool*)addr ? "true" : "false");CHKERRQ(ierr); 950 ierr = PetscStrcat(*result,"\"]");CHKERRQ(ierr); 951 } else { 952 ierr = PetscStrallocpy("Not yet done",result);CHKERRQ(ierr); 953 } 954 } 955 PetscFunctionReturn(0); 956 } 957 958 #undef __FUNCT__ 959 #define __FUNCT__ "YAML_AMS_Connect" 960 /* 961 Connects to the local AMS and gets only the first communication name 962 963 Input Parameters: 964 . none 965 966 Output Parameter: 967 . oarg1 - the string name of the first communicator 968 969 */ 970 PETSC_EXTERN PetscErrorCode YAML_AMS_Connect(PetscInt argc,char **args,PetscInt *argco,char ***argso) 971 { 972 PetscErrorCode ierr; 973 char **list = 0; 974 PetscInt n = 0; 975 976 PetscFunctionBegin; 977 ierr = AMS_Connect(0,-1,&list); 978 if (ierr) { 979 ierr = PetscInfo1(NULL,"AMS_Connect() error %d\n",ierr);CHKERRQ(ierr); 980 } else if (!list) { 981 ierr = PetscInfo(NULL,"AMS_Connect() list empty, not running AMS server\n");CHKERRQ(ierr); 982 } 983 *argco = 1; 984 ierr = PetscMalloc(sizeof(char*),argso);CHKERRQ(ierr); 985 if (list) { 986 while (list[n]) n++; 987 ierr = YAML_AMS_Utility_ArrayToString(n,list,AMS_STRING,&(*argso)[0]);CHKERRQ(ierr); 988 } else { 989 ierr = PetscStrallocpy("No AMS publisher running",&(*argso)[0]);CHKERRQ(ierr); 990 } 991 PetscFunctionReturn(0); 992 } 993 994 #undef __FUNCT__ 995 #define __FUNCT__ "YAML_AMS_Comm_attach" 996 /* 997 Attaches to an AMS communicator 998 999 Input Parameter: 1000 . arg1 - string name of the communicator 1001 1002 Output Parameter: 1003 . oarg1 - the integer name of the communicator 1004 1005 */ 1006 PETSC_EXTERN PetscErrorCode YAML_AMS_Comm_attach(PetscInt argc,char **args,PetscInt *argco,char ***argso) 1007 { 1008 PetscErrorCode ierr; 1009 AMS_Comm comm = -1; 1010 1011 PetscFunctionBegin; 1012 ierr = AMS_Comm_attach(args[0],&comm); 1013 if (ierr) { 1014 ierr = PetscInfo1(NULL,"AMS_Comm_attach() error %d\n",ierr);CHKERRQ(ierr); 1015 } 1016 *argco = 1; 1017 ierr = PetscMalloc(sizeof(char*),argso);CHKERRQ(ierr); 1018 ierr = PetscMalloc(3*sizeof(char*),&argso[0][0]);CHKERRQ(ierr); 1019 sprintf(argso[0][0],"%d",(int)comm); 1020 PetscFunctionReturn(0); 1021 } 1022 1023 #undef __FUNCT__ 1024 #define __FUNCT__ "YAML_AMS_Comm_get_memory_list" 1025 /* 1026 Gets the list of memories on an AMS Comm 1027 1028 Input Parameter: 1029 . arg1 - integer name of the communicator 1030 1031 Output Parameter: 1032 . oarg1 - the list of names 1033 1034 */ 1035 PETSC_EXTERN PetscErrorCode YAML_AMS_Comm_get_memory_list(PetscInt argc,char **args,PetscInt *argco,char ***argso) 1036 { 1037 PetscErrorCode ierr; 1038 char **mem_list; 1039 AMS_Comm comm; 1040 PetscInt i,iargco = 0; 1041 1042 PetscFunctionBegin; 1043 sscanf(args[0],"%d",&comm); 1044 ierr = AMS_Comm_get_memory_list(comm,&mem_list); 1045 if (ierr) { 1046 ierr = PetscInfo1(NULL,"AMS_Comm_get_memory_list() error %d\n",ierr);CHKERRQ(ierr); 1047 } else { 1048 while (mem_list[iargco++]) ; 1049 iargco--; 1050 1051 ierr = PetscMalloc((iargco)*sizeof(char*),argso);CHKERRQ(ierr); 1052 for (i=0; i<iargco; i++) { 1053 ierr = PetscStrallocpy(mem_list[i],(*argso)+i);CHKERRQ(ierr); 1054 } 1055 } 1056 *argco = iargco; 1057 PetscFunctionReturn(0); 1058 } 1059 1060 #undef __FUNCT__ 1061 #define __FUNCT__ "YAML_AMS_Memory_attach" 1062 /* 1063 Attaches to an AMS memory in a communicator 1064 1065 Input Parameter: 1066 . arg1 - communicator 1067 . arg2 - string name of the memory 1068 1069 Output Parameter: 1070 . oarg1 - the integer name of the memory 1071 . oarg2 - the integer step of the memory 1072 1073 */ 1074 PETSC_EXTERN PetscErrorCode YAML_AMS_Memory_attach(PetscInt argc,char **args,PetscInt *argco,char ***argso) 1075 { 1076 PetscErrorCode ierr; 1077 AMS_Comm comm; 1078 AMS_Memory mem; 1079 unsigned int step; 1080 1081 PetscFunctionBegin; 1082 sscanf(args[0],"%d",&comm); 1083 ierr = AMS_Memory_attach(comm,args[1],&mem,&step); 1084 if (ierr) {ierr = PetscInfo1(NULL,"AMS_Memory_attach() error %d\n",ierr);CHKERRQ(ierr);} 1085 *argco = 2; 1086 ierr = PetscMalloc(2*sizeof(char*),argso);CHKERRQ(ierr); 1087 ierr = PetscMalloc(3*sizeof(char*),&argso[0][0]);CHKERRQ(ierr); 1088 sprintf(argso[0][0],"%d",(int)mem); 1089 ierr = PetscMalloc(3*sizeof(char*),&argso[0][1]);CHKERRQ(ierr); 1090 sprintf(argso[0][1],"%d",(int)step); 1091 PetscFunctionReturn(0); 1092 } 1093 1094 #undef __FUNCT__ 1095 #define __FUNCT__ "YAML_AMS_Memory_get_field_list" 1096 /* 1097 Gets the list of fields on an AMS Memory 1098 1099 Input Parameter: 1100 . arg1 - integer name of the memory 1101 1102 Output Parameter: 1103 . oarg1 - the list of names 1104 1105 */ 1106 PETSC_EXTERN PetscErrorCode YAML_AMS_Memory_get_field_list(PetscInt argc,char **args,PetscInt *argco,char ***argso) 1107 { 1108 PetscErrorCode ierr; 1109 char **field_list; 1110 AMS_Memory mem; 1111 PetscInt i,iargco = 0; 1112 1113 PetscFunctionBegin; 1114 sscanf(args[0],"%d",&mem); 1115 ierr = AMS_Memory_get_field_list(mem,&field_list); 1116 if (ierr) { 1117 ierr = PetscInfo1(NULL,"AMS_Memory_get_field_list() error %d\n",ierr);CHKERRQ(ierr); 1118 } else { 1119 while (field_list[iargco++]) ; 1120 iargco--; 1121 1122 ierr = PetscMalloc((iargco)*sizeof(char*),argso);CHKERRQ(ierr); 1123 for (i=0; i<iargco; i++) { 1124 ierr = PetscStrallocpy(field_list[i],(*argso)+i);CHKERRQ(ierr); 1125 } 1126 } 1127 *argco = iargco; 1128 PetscFunctionReturn(0); 1129 } 1130 1131 const char *AMS_Data_types[] = {"AMS_DATA_UNDEF","AMS_BOOLEAN","AMS_INT","AMS_FLOAT","AMS_DOUBLE","AMS_STRING","AMS_Data_type","AMS_",0}; 1132 const char *AMS_Memory_types[] = {"AMS_MEMORY_UNDEF","AMS_READ","AMS_WRITE","AMS_Memory_type","AMS_",0}; 1133 const char *AMS_Shared_types[] = {"AMS_SHARED_UNDEF","AMS_COMMON","AMS_REDUCED","AMS_DISTRIBUTED","AMS_Shared_type","AMS_",0}; 1134 const char *AMS_Reduction_types[] = {"AMS_REDUCTION_WHY_NOT_UNDEF?","AMS_SUM","AMS_MAX","AMS_MIN","AMS_REDUCTION_UNDEF","AMS_Reduction_type","AMS_",0}; 1135 1136 1137 #undef __FUNCT__ 1138 #define __FUNCT__ "YAML_AMS_Memory_get_field_info" 1139 /* 1140 Gets information about a field 1141 1142 Input Parameter: 1143 . arg1 - memory 1144 . arg2 - string name of the field 1145 1146 Output Parameter: 1147 1148 */ 1149 PETSC_EXTERN PetscErrorCode YAML_AMS_Memory_get_field_info(PetscInt argc,char **args,PetscInt *argco,char ***argso) 1150 { 1151 PetscErrorCode ierr; 1152 AMS_Memory mem; 1153 char *addr; 1154 int len; 1155 AMS_Data_type dtype; 1156 AMS_Memory_type mtype; 1157 AMS_Shared_type stype; 1158 AMS_Reduction_type rtype; 1159 1160 PetscFunctionBegin; 1161 sscanf(args[0],"%d",&mem); 1162 ierr = AMS_Memory_get_field_info(mem,args[1],(void**)&addr,&len,&dtype,&mtype,&stype,&rtype); 1163 if (ierr) {ierr = PetscInfo1(NULL,"AMS_Memory_get_field_info() error %d\n",ierr);CHKERRQ(ierr);} 1164 *argco = 5; 1165 ierr = PetscMalloc((*argco)*sizeof(char*),argso);CHKERRQ(ierr); 1166 ierr = PetscStrallocpy(AMS_Data_types[dtype],&argso[0][0]);CHKERRQ(ierr); 1167 ierr = PetscStrallocpy(AMS_Memory_types[mtype],&argso[0][1]);CHKERRQ(ierr); 1168 ierr = PetscStrallocpy(AMS_Shared_types[stype],&argso[0][2]);CHKERRQ(ierr); 1169 ierr = PetscStrallocpy(AMS_Reduction_types[rtype],&argso[0][3]);CHKERRQ(ierr); 1170 ierr = YAML_AMS_Utility_ArrayToString(len,addr,dtype,&argso[0][4]);CHKERRQ(ierr); 1171 PetscFunctionReturn(0); 1172 } 1173 1174 #include "yaml.h" 1175 #undef __FUNCT__ 1176 #define __FUNCT__ "PetscProcessYAMLRPC" 1177 /* 1178 1) Parses a YAML/JSON-RPC function call generating a function name for an AMS wrapper function and the arguments to the function 1179 2) loads the function with dlsym(), 1180 3) calls the wrapper function with the arguments 1181 4) converts the result arguments back to YAML/JSON. 1182 */ 1183 static PetscErrorCode PetscProcessYAMLRPC(const char *request,char **result) 1184 { 1185 yaml_parser_t parser; 1186 yaml_event_t event; 1187 int done = 0; 1188 int count = 0; 1189 size_t len; 1190 PetscErrorCode ierr; 1191 PetscBool method,params,id; 1192 char *methodname,*idname,**args,**argso = 0; 1193 PetscInt argc = 0,argco,i; 1194 PetscErrorCode (*fun)(PetscInt,char**,PetscInt*,char***); 1195 1196 PetscFunctionBegin; 1197 ierr = PetscMalloc(sizeof(char*),&args);CHKERRQ(ierr); 1198 yaml_parser_initialize(&parser); 1199 PetscStrlen(request,&len); 1200 yaml_parser_set_input_string(&parser, (unsigned char*)request, len); 1201 1202 /* this is totally bogus; it only handles the simple JSON-RPC messages */ 1203 while (!done) { 1204 if (!yaml_parser_parse(&parser, &event)) { 1205 ierr = PetscInfo(NULL,"Found error in yaml/json\n");CHKERRQ(ierr); 1206 break; 1207 } 1208 done = (event.type == YAML_STREAM_END_EVENT); 1209 switch (event.type) { 1210 case YAML_STREAM_START_EVENT: 1211 ierr = PetscInfo(NULL,"Stream start\n");CHKERRQ(ierr); 1212 break; 1213 case YAML_STREAM_END_EVENT: 1214 ierr = PetscInfo(NULL,"Stream end\n");CHKERRQ(ierr); 1215 break; 1216 case YAML_DOCUMENT_START_EVENT: 1217 ierr = PetscInfo(NULL,"Document start\n");CHKERRQ(ierr); 1218 break; 1219 case YAML_DOCUMENT_END_EVENT: 1220 ierr = PetscInfo(NULL,"Document end\n");CHKERRQ(ierr); 1221 break; 1222 case YAML_MAPPING_START_EVENT: 1223 ierr = PetscInfo(NULL,"Mapping start event\n");CHKERRQ(ierr); 1224 break; 1225 case YAML_MAPPING_END_EVENT: 1226 ierr = PetscInfo(NULL,"Mapping end event \n");CHKERRQ(ierr); 1227 break; 1228 case YAML_ALIAS_EVENT: 1229 ierr = PetscInfo1(NULL,"Alias event %s\n",event.data.alias.anchor);CHKERRQ(ierr); 1230 break; 1231 case YAML_SCALAR_EVENT: 1232 ierr = PetscInfo1(NULL,"Scalar event %s\n",event.data.scalar.value);CHKERRQ(ierr); 1233 ierr = PetscStrcmp((char*)event.data.scalar.value,"method",&method);CHKERRQ(ierr); 1234 ierr = PetscStrcmp((char*)event.data.scalar.value,"params",¶ms);CHKERRQ(ierr); 1235 ierr = PetscStrcmp((char*)event.data.scalar.value,"id",&id);CHKERRQ(ierr); 1236 if (method) { 1237 yaml_event_delete(&event); 1238 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1239 ierr = PetscInfo1(NULL,"Method %s\n",event.data.scalar.value);CHKERRQ(ierr); 1240 ierr = PetscStrallocpy((char*)event.data.scalar.value,&methodname);CHKERRQ(ierr); 1241 } else if (id) { 1242 yaml_event_delete(&event); 1243 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1244 ierr = PetscInfo1(NULL,"Id %s\n",event.data.scalar.value);CHKERRQ(ierr); 1245 ierr = PetscStrallocpy((char*)event.data.scalar.value,&idname);CHKERRQ(ierr); 1246 } else if (params) { 1247 yaml_event_delete(&event); 1248 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1249 yaml_event_delete(&event); 1250 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1251 while (event.type != YAML_SEQUENCE_END_EVENT) { 1252 ierr = PetscInfo1(NULL," Parameter %s\n",event.data.scalar.value);CHKERRQ(ierr); 1253 ierr = PetscStrallocpy((char*)event.data.scalar.value,&args[argc++]);CHKERRQ(ierr); 1254 yaml_event_delete(&event); 1255 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1256 } 1257 } else { /* ignore all the other variables in the mapping */ 1258 yaml_event_delete(&event); 1259 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1260 } 1261 break; 1262 case YAML_SEQUENCE_START_EVENT: 1263 ierr = PetscInfo(NULL,"Sequence start event \n");CHKERRQ(ierr); 1264 break; 1265 case YAML_SEQUENCE_END_EVENT: 1266 ierr = PetscInfo(NULL,"Sequence end event \n");CHKERRQ(ierr); 1267 break; 1268 default: 1269 /* It couldn't really happen. */ 1270 break; 1271 } 1272 1273 yaml_event_delete(&event); 1274 count++; 1275 } 1276 yaml_parser_delete(&parser); 1277 1278 ierr = PetscDLLibrarySym(PETSC_COMM_SELF,NULL,NULL,methodname,(void**)&fun);CHKERRQ(ierr); 1279 if (fun) { 1280 ierr = PetscInfo1(NULL,"Located function %s and running it\n",methodname);CHKERRQ(ierr); 1281 ierr = (*fun)(argc,args,&argco,&argso);CHKERRQ(ierr); 1282 } else { 1283 ierr = PetscInfo1(NULL,"Did not locate function %s skipping it\n",methodname);CHKERRQ(ierr); 1284 } 1285 1286 for (i=0; i<argc; i++) { 1287 ierr = PetscFree(args[i]);CHKERRQ(ierr); 1288 } 1289 ierr = PetscFree(args);CHKERRQ(ierr); 1290 ierr = PetscFree(methodname);CHKERRQ(ierr); 1291 1292 /* convert the result back to YAML/JSON; should use YAML/JSON encoder, does not handle zero return arguments */ 1293 ierr = PetscMalloc(16000,result);CHKERRQ(ierr); 1294 ierr = PetscStrcpy(*result,"{\"error\": null, \"id\": \"");CHKERRQ(ierr); 1295 ierr = PetscStrcat(*result,idname);CHKERRQ(ierr); 1296 ierr = PetscStrcat(*result,"\", \"result\" : ");CHKERRQ(ierr); 1297 if (argco > 1) {ierr = PetscStrcat(*result,"[");CHKERRQ(ierr);} 1298 for (i=0; i<argco; i++) { 1299 if (argso[i][0] != '[') { 1300 ierr = PetscStrcat(*result,"\"");CHKERRQ(ierr); 1301 } 1302 ierr = PetscStrcat(*result,argso[i]);CHKERRQ(ierr); 1303 if (argso[i][0] != '[') { 1304 ierr = PetscStrcat(*result,"\"");CHKERRQ(ierr); 1305 } 1306 if (i < argco-1) {ierr = PetscStrcat(*result,",");CHKERRQ(ierr);} 1307 } 1308 if (argco > 1) {ierr = PetscStrcat(*result,"]");CHKERRQ(ierr);} 1309 ierr = PetscStrcat(*result,"}");CHKERRQ(ierr); 1310 ierr = PetscInfo1(NULL,"YAML/JSON result of function %s\n",*result);CHKERRQ(ierr); 1311 1312 /* free work space */ 1313 ierr = PetscFree(idname);CHKERRQ(ierr); 1314 for (i=0; i<argco; i++) { 1315 ierr = PetscFree(argso[i]);CHKERRQ(ierr); 1316 } 1317 ierr = PetscFree(argso);CHKERRQ(ierr); 1318 PetscFunctionReturn(0); 1319 } 1320 1321 #undef __FUNCT__ 1322 #define __FUNCT__ "PetscWebServeRequestPostAMSJSONRPC" 1323 /*@C 1324 PetscWebServeRequestPostAMSJSONRPC - serves a single web POST request based on JSON-RPC 1325 1326 This function allows a Javascript program (running in the browser) to make an AMS function 1327 call via JSON-RPC 1328 1329 The currently available Javascript programs are in ${PETSC_DIR}/include/web 1330 1331 Not collective 1332 1333 Input Parameters: 1334 . fd - the network file to read and write from 1335 - path - the command from the server 1336 1337 Level: developer 1338 1339 .seealso: PetscWebServe() 1340 @*/ 1341 static PetscErrorCode PetscWebServeRequestPostAMSJSONRPC(FILE *fd,const char path[]) 1342 { 1343 PetscErrorCode ierr; 1344 char buf[16000]; 1345 char *result; 1346 int len = -1; 1347 size_t elen; 1348 char *fnd; 1349 1350 PetscFunctionBegin; 1351 while (PETSC_TRUE) { 1352 if (!fgets(buf, sizeof(buf), fd)) { 1353 ierr = PetscInfo(NULL,"Cannot read POST data, giving up\n");CHKERRQ(ierr); 1354 PetscFunctionReturn(0); 1355 } 1356 ierr = PetscInfo1(NULL,"POSTED header: %s",buf);CHKERRQ(ierr); 1357 ierr = PetscStrstr(buf,"Content-Type:",&fnd);CHKERRQ(ierr); 1358 if (fnd) { 1359 ierr = PetscStrstr(buf,"application/json-rpc",&fnd);CHKERRQ(ierr); 1360 if (!fnd) { 1361 ierr = PetscInfo(NULL,"POSTED content is not json-rpc, skipping post\n");CHKERRQ(ierr); 1362 PetscFunctionReturn(0); 1363 } 1364 } 1365 ierr = PetscStrstr(buf,"Content-Length:",&fnd);CHKERRQ(ierr); 1366 if (fnd) { 1367 sscanf(buf,"Content-Length: %d\n",&len); 1368 ierr = PetscInfo1(NULL,"POSTED Content-Length: %d\n",len);CHKERRQ(ierr); 1369 } 1370 if (buf[0] == '\r') break; 1371 } 1372 if (len == -1) { 1373 ierr = PetscInfo(NULL,"Did not find POST Content-Length in header, giving up\n");CHKERRQ(ierr); 1374 } 1375 1376 if (!fgets(buf, len+1, fd)) { /* why is this len + 1? */ 1377 ierr = PetscInfo(NULL,"Cannot read POST data, giving up\n");CHKERRQ(ierr); 1378 PetscFunctionReturn(0); 1379 } 1380 ierr = PetscInfo1(NULL,"POSTED JSON/RPC request: %s\n",buf);CHKERRQ(ierr); 1381 fseek(fd, 0, SEEK_CUR); /* Force change of stream direction */ 1382 ierr = PetscProcessYAMLRPC(buf,&result);CHKERRQ(ierr); 1383 ierr = PetscStrlen(result,&elen);CHKERRQ(ierr); 1384 ierr = PetscWebSendHeader(fd, 200, "OK", NULL, "application/json-rpc",(int)elen);CHKERRQ(ierr); 1385 fprintf(fd, "%s",result); 1386 ierr = PetscInfo(NULL,"Completed AMS JSON-RPC function call\n");CHKERRQ(ierr); 1387 PetscFunctionReturn(0); 1388 } 1389 #endif 1390 1391 #undef __FUNCT__ 1392 #define __FUNCT__ "PetscWebServeRequest" 1393 /*@C 1394 PetscWebServeRequest - serves a single web request 1395 1396 Not collective 1397 1398 Input Parameters: 1399 . port - the port 1400 1401 Level: developer 1402 1403 .seealso: PetscWebServe() 1404 @*/ 1405 static PetscErrorCode PetscWebServeRequest(int port) 1406 { 1407 PetscErrorCode ierr; 1408 FILE *fd; 1409 char buf[4096]; 1410 char *method, *path, *protocol; 1411 PetscBool flg; 1412 PetscToken tok; 1413 1414 PetscFunctionBegin; 1415 fd = fdopen(port, "r+"); 1416 1417 ierr = PetscInfo(NULL,"Processing web request\n");CHKERRQ(ierr); 1418 if (!fgets(buf, sizeof(buf), fd)) { 1419 ierr = PetscInfo(NULL,"Cannot read web request, giving up\n");CHKERRQ(ierr); 1420 goto theend; 1421 } 1422 ierr = PetscInfo1(NULL,"Processing web request %s",buf);CHKERRQ(ierr); 1423 1424 ierr = PetscTokenCreate(buf,' ',&tok);CHKERRQ(ierr); 1425 ierr = PetscTokenFind(tok,&method);CHKERRQ(ierr); 1426 ierr = PetscTokenFind(tok,&path);CHKERRQ(ierr); 1427 ierr = PetscTokenFind(tok,&protocol);CHKERRQ(ierr); 1428 1429 if (!method || !path || !protocol) { 1430 ierr = PetscInfo(NULL,"Web request not well formatted, giving up\n");CHKERRQ(ierr); 1431 goto theend; 1432 } 1433 1434 ierr = PetscStrcmp(method,"GET",&flg); 1435 if (flg) { 1436 ierr = PetscWebServeRequestGet(fd,path);CHKERRQ(ierr); 1437 } else { 1438 #if defined(PETSC_HAVE_YAML) 1439 ierr = PetscStrcmp(method,"POST",&flg); 1440 if (flg) { 1441 ierr = PetscWebServeRequestPostAMSJSONRPC(fd,path);CHKERRQ(ierr); 1442 } else { 1443 #else 1444 { 1445 #endif 1446 ierr = PetscWebSendError(fd, 501, "Not supported", NULL, "Method is not supported.");CHKERRQ(ierr); 1447 ierr = PetscInfo(NULL,"Web request not a GET or POST, giving up\n");CHKERRQ(ierr); 1448 } 1449 } 1450 theend: 1451 ierr = PetscTokenDestroy(&tok);CHKERRQ(ierr); 1452 fclose(fd); 1453 ierr = PetscInfo1(NULL,"Finished processing request %s\n",method);CHKERRQ(ierr); 1454 PetscFunctionReturn(0); 1455 } 1456 1457 #undef __FUNCT__ 1458 #define __FUNCT__ "PetscWebServeWait" 1459 /*@C 1460 PetscWebServeWait - waits for requests on a thread 1461 1462 Not collective 1463 1464 Input Parameter: 1465 . port - port to listen on 1466 1467 Level: developer 1468 1469 .seealso: PetscViewerSocketOpen(), PetscWebServe() 1470 @*/ 1471 void *PetscWebServeWait(int *port) 1472 { 1473 PetscErrorCode ierr; 1474 int iport,listenport,tport = *port; 1475 1476 ierr = PetscInfo1(NULL,"Starting webserver at port %d\n",tport);if (ierr) return 0; 1477 ierr = PetscFree(port);if (ierr) return 0; 1478 ierr = PetscSocketEstablish(tport,&listenport);if (ierr) return 0; 1479 while (1) { 1480 ierr = PetscSocketListen(listenport,&iport);if (ierr) return 0; 1481 ierr = PetscWebServeRequest(iport);if (ierr) return 0; 1482 close(iport); 1483 } 1484 close(listenport); 1485 return 0; 1486 } 1487 1488 #undef __FUNCT__ 1489 #define __FUNCT__ "PetscWebServe" 1490 /*@C 1491 PetscWebServe - start up the PETSc web server and respond to requests 1492 1493 Not collective - only does something on process zero of the communicator 1494 1495 Input Parameters: 1496 + comm - the MPI communicator 1497 - port - port to listen on 1498 1499 Options Database Key: 1500 + -server <port> - start PETSc webserver (default port is 8080) 1501 - -xxx_view ams - publish object xxx to be accessible in the server 1502 1503 1504 Notes: Point your browser to http://hostname:8080 to access the PETSc web server, where hostname is the name of your machine. 1505 If you are running PETSc on your local machine you can use http://localhost:8080 1506 1507 If the PETSc program completes before you connect with the browser you will not be able to connect to the PETSc webserver. 1508 1509 Read the top of $PETSC_DIR/include/web/AMSJavascript.py before running. 1510 1511 Level: intermediate 1512 1513 .seealso: PetscViewerSocketOpen() 1514 @*/ 1515 PetscErrorCode PetscWebServe(MPI_Comm comm,int port) 1516 { 1517 PetscErrorCode ierr; 1518 PetscMPIInt rank; 1519 pthread_t thread; 1520 int *trueport; 1521 1522 PetscFunctionBegin; 1523 if (port < 1 && port != PETSC_DEFAULT && port != PETSC_DECIDE) SETERRQ1(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,"Cannot use negative port number %d",port); 1524 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1525 if (rank) PetscFunctionReturn(0); 1526 1527 if (port == PETSC_DECIDE || port == PETSC_DEFAULT) port = 8080; 1528 ierr = PetscMalloc(1*sizeof(int),&trueport);CHKERRQ(ierr); /* malloc this so it still exists in thread */ 1529 *trueport = port; 1530 ierr = pthread_create(&thread, NULL, (void *(*)(void*))PetscWebServeWait, trueport);CHKERRQ(ierr); 1531 PetscFunctionReturn(0); 1532 } 1533 #endif 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548