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