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