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 747 PetscFunctionReturn(0); 748 } 749 #endif 750 751 #if defined(PETSC_HAVE_YAML) 752 753 EXTERN_C_BEGIN 754 /* 755 Toy function that returns all the arguments it is passed 756 */ 757 #undef __FUNCT__ 758 #define __FUNCT__ "YAML_echo" 759 PetscErrorCode YAML_echo(PetscInt argc,char **args,PetscInt *argco,char ***argso) 760 { 761 PetscErrorCode ierr; 762 PetscInt i; 763 764 ierr = PetscPrintf(PETSC_COMM_SELF,"Number of arguments to function %d\n",argc);CHKERRQ(ierr); 765 for (i=0; i<argc; i++) { 766 ierr = PetscPrintf(PETSC_COMM_SELF," %s\n",args[i]);CHKERRQ(ierr); 767 } 768 *argco = argc; 769 ierr = PetscMalloc(argc*sizeof(char*),argso);CHKERRQ(ierr); 770 for (i=0; i<argc; i++) { 771 ierr = PetscStrallocpy(args[i],&(*argso)[i]);CHKERRQ(ierr); 772 } 773 PetscFunctionReturn(0); 774 } 775 EXTERN_C_END 776 777 EXTERN_C_BEGIN 778 #undef __FUNCT__ 779 #define __FUNCT__ "YAML_AMS_Connect" 780 /* 781 Connects to the local AMS and gets only the first communication name 782 783 Input Parameters: 784 . none 785 786 Output Parameter: 787 . oarg1 - the string name of the first communicator 788 789 */ 790 PetscErrorCode YAML_AMS_Connect(PetscInt argc,char **args,PetscInt *argco,char ***argso) 791 { 792 PetscErrorCode ierr; 793 char **list = 0; 794 795 PetscFunctionBegin; 796 ierr = AMS_Connect(0,-1,&list); 797 if (ierr) {ierr = PetscInfo1(PETSC_NULL,"AMS_Connect() error %d\n",ierr);CHKERRQ(ierr);} 798 else if (!list) {ierr = PetscInfo(PETSC_NULL,"AMS_Connect() list empty, not running AMS server\n");CHKERRQ(ierr);} 799 *argco = 1; 800 ierr = PetscMalloc(sizeof(char*),argso);CHKERRQ(ierr); 801 if (list){ 802 ierr = PetscStrallocpy(list[0],&(*argso)[0]);CHKERRQ(ierr); 803 } else { 804 ierr = PetscStrallocpy("No AMS publisher running",&(*argso)[0]);CHKERRQ(ierr); 805 } 806 PetscFunctionReturn(0); 807 } 808 EXTERN_C_END 809 810 EXTERN_C_BEGIN 811 #undef __FUNCT__ 812 #define __FUNCT__ "YAML_AMS_Comm_attach" 813 /* 814 Attaches to an AMS communicator 815 816 Input Parameter: 817 . arg1 - string name of the communicator 818 819 Output Parameter: 820 . oarg1 - the integer name of the communicator 821 822 */ 823 PetscErrorCode YAML_AMS_Comm_attach(PetscInt argc,char **args,PetscInt *argco,char ***argso) 824 { 825 PetscErrorCode ierr; 826 AMS_Comm comm = -1; 827 828 PetscFunctionBegin; 829 ierr = AMS_Comm_attach(args[0],&comm); 830 if (ierr) {ierr = PetscInfo1(PETSC_NULL,"AMS_Comm_attach() error %d\n",ierr);CHKERRQ(ierr);} 831 *argco = 1; 832 ierr = PetscMalloc(sizeof(char*),argso);CHKERRQ(ierr); 833 ierr = PetscMalloc(3*sizeof(char*),&argso[0][0]);CHKERRQ(ierr); 834 sprintf(argso[0][0],"%d",(int)comm); 835 PetscFunctionReturn(0); 836 } 837 EXTERN_C_END 838 839 EXTERN_C_BEGIN 840 #undef __FUNCT__ 841 #define __FUNCT__ "YAML_AMS_Comm_get_memory_list" 842 /* 843 Gets the list of memories on an AMS Comm 844 845 Input Parameter: 846 . arg1 - integer name of the communicator 847 848 Output Parameter: 849 . oarg1 - the list of names 850 851 */ 852 PetscErrorCode YAML_AMS_Comm_get_memory_list(PetscInt argc,char **args,PetscInt *argco,char ***argso) 853 { 854 PetscErrorCode ierr; 855 char **mem_list; 856 AMS_Comm comm; 857 PetscInt i,iargco = 0; 858 859 PetscFunctionBegin; 860 sscanf(args[0],"%d",&comm); 861 ierr = AMS_Comm_get_memory_list(comm,&mem_list); 862 if (ierr) { 863 ierr = PetscInfo1(PETSC_NULL,"AMS_Comm_get_memory_list() error %d\n",ierr);CHKERRQ(ierr); 864 } else { 865 while (mem_list[iargco++]) ; 866 iargco--; 867 868 ierr = PetscMalloc((iargco)*sizeof(char*),argso);CHKERRQ(ierr); 869 for (i=0; i<iargco; i++) { 870 ierr = PetscStrallocpy(mem_list[i],(*argso)+i);CHKERRQ(ierr); 871 } 872 } 873 *argco = iargco; 874 PetscFunctionReturn(0); 875 } 876 EXTERN_C_END 877 878 EXTERN_C_BEGIN 879 #undef __FUNCT__ 880 #define __FUNCT__ "YAML_AMS_Memory_attach" 881 /* 882 Attaches to an AMS memory in a communicator 883 884 Input Parameter: 885 . arg1 - communicator 886 . arg2 - string name of the memory 887 888 Output Parameter: 889 . oarg1 - the integer name of the memory 890 . oarg2 - the integer step of the memory 891 892 */ 893 PetscErrorCode YAML_AMS_Memory_attach(PetscInt argc,char **args,PetscInt *argco,char ***argso) 894 { 895 PetscErrorCode ierr; 896 AMS_Comm comm; 897 AMS_Memory mem; 898 unsigned int step; 899 900 PetscFunctionBegin; 901 sscanf(args[0],"%d",&comm); 902 ierr = AMS_Memory_attach(comm,args[1],&mem,&step); 903 if (ierr) {ierr = PetscInfo1(PETSC_NULL,"AMS_Memory_attach() error %d\n",ierr);CHKERRQ(ierr);} 904 *argco = 2; 905 ierr = PetscMalloc(2*sizeof(char*),argso);CHKERRQ(ierr); 906 ierr = PetscMalloc(3*sizeof(char*),&argso[0][0]);CHKERRQ(ierr); 907 sprintf(argso[0][0],"%d",(int)mem); 908 ierr = PetscMalloc(3*sizeof(char*),&argso[0][1]);CHKERRQ(ierr); 909 sprintf(argso[0][1],"%d",(int)step); 910 PetscFunctionReturn(0); 911 } 912 EXTERN_C_END 913 914 EXTERN_C_BEGIN 915 #undef __FUNCT__ 916 #define __FUNCT__ "YAML_AMS_Memory_get_field_list" 917 /* 918 Gets the list of fields on an AMS Memory 919 920 Input Parameter: 921 . arg1 - integer name of the memory 922 923 Output Parameter: 924 . oarg1 - the list of names 925 926 */ 927 PetscErrorCode YAML_AMS_Memory_get_field_list(PetscInt argc,char **args,PetscInt *argco,char ***argso) 928 { 929 PetscErrorCode ierr; 930 char **field_list; 931 AMS_Memory mem; 932 PetscInt i,iargco = 0; 933 934 PetscFunctionBegin; 935 sscanf(args[0],"%d",&mem); 936 ierr = AMS_Memory_get_field_list(mem,&field_list); 937 if (ierr) { 938 ierr = PetscInfo1(PETSC_NULL,"AMS_Memory_get_field_list() error %d\n",ierr);CHKERRQ(ierr); 939 } else { 940 while (field_list[iargco++]) ; 941 iargco--; 942 943 ierr = PetscMalloc((iargco)*sizeof(char*),argso);CHKERRQ(ierr); 944 for (i=0; i<iargco; i++) { 945 ierr = PetscStrallocpy(field_list[i],(*argso)+i);CHKERRQ(ierr); 946 } 947 } 948 *argco = iargco; 949 PetscFunctionReturn(0); 950 } 951 EXTERN_C_END 952 953 const char *AMS_Data_types[] = {"AMS_DATA_UNDEF","AMS_BOOLEAN","AMS_INT","AMS_FLOAT","AMS_DOUBLE","AMS_STRING","AMS_Data_type","AMS_",0}; 954 const char *AMS_Memory_types[] = {"AMS_MEMORY_UNDEF","AMS_READ","AMS_WRITE","AMS_Memory_type","AMS_",0}; 955 const char *AMS_Shared_types[] = {"AMS_SHARED_UNDEF","AMS_COMMON","AMS_REDUCED","AMS_DISTRIBUTED","AMS_Shared_type","AMS_",0}; 956 const char *AMS_Reduction_types[] = {"AMS_REDUCTION_WHY_NOT_UNDEF?","AMS_SUM","AMS_MAX","AMS_MIN","AMS_REDUCTION_UNDEF","AMS_Reduction_type","AMS_",0}; 957 958 EXTERN_C_BEGIN 959 #undef __FUNCT__ 960 #define __FUNCT__ "YAML_AMS_Memory_get_field_info" 961 /* 962 Gets information about a field 963 964 Input Parameter: 965 . arg1 - memory 966 . arg2 - string name of the field 967 968 Output Parameter: 969 970 */ 971 PetscErrorCode YAML_AMS_Memory_get_field_info(PetscInt argc,char **args,PetscInt *argco,char ***argso) 972 { 973 PetscErrorCode ierr; 974 AMS_Memory mem; 975 void *addr; 976 int len; 977 AMS_Data_type dtype; 978 AMS_Memory_type mtype; 979 AMS_Shared_type stype; 980 AMS_Reduction_type rtype; 981 PetscInt i; 982 983 PetscFunctionBegin; 984 sscanf(args[0],"%d",&mem); 985 ierr = AMS_Memory_get_field_info(mem,args[1],&addr,&len,&dtype,&mtype,&stype,&rtype); 986 if (ierr) {ierr = PetscInfo1(PETSC_NULL,"AMS_Memory_get_field_info() error %d\n",ierr);CHKERRQ(ierr);} 987 *argco = 4 + len; 988 ierr = PetscMalloc((*argco)*sizeof(char*),argso);CHKERRQ(ierr); 989 ierr = PetscStrallocpy(AMS_Data_types[dtype],&argso[0][0]);CHKERRQ(ierr); 990 ierr = PetscStrallocpy(AMS_Memory_types[mtype],&argso[0][1]);CHKERRQ(ierr); 991 ierr = PetscStrallocpy(AMS_Shared_types[stype],&argso[0][2]);CHKERRQ(ierr); 992 ierr = PetscStrallocpy(AMS_Reduction_types[rtype],&argso[0][3]);CHKERRQ(ierr); 993 for (i=0; i<len; i++) { 994 if (dtype == AMS_STRING) { 995 ierr = PetscStrallocpy(*(const char **)addr,&argso[0][4+i]);CHKERRQ(ierr); 996 } else if (dtype == AMS_DOUBLE) { 997 ierr = PetscMalloc(20*sizeof(char),&argso[0][4+i]);CHKERRQ(ierr); 998 sprintf(argso[0][4+i],"%18.16e",*(double*)addr); 999 } else if (dtype == AMS_INT) { 1000 ierr = PetscMalloc(10*sizeof(char),&argso[0][4+i]);CHKERRQ(ierr); 1001 sprintf(argso[0][4+i],"%d",*(int*)addr); 1002 } else if (dtype == AMS_BOOLEAN) { 1003 if (*(int*)addr) { 1004 ierr = PetscStrallocpy("true",&argso[0][4+i]);CHKERRQ(ierr); 1005 } else { 1006 ierr = PetscStrallocpy("false",&argso[0][4+i]);CHKERRQ(ierr); 1007 } 1008 } else { 1009 ierr = PetscStrallocpy("Not yet done",&argso[0][4+i]);CHKERRQ(ierr); 1010 } 1011 } 1012 PetscFunctionReturn(0); 1013 } 1014 EXTERN_C_END 1015 1016 #include "yaml.h" 1017 #undef __FUNCT__ 1018 #define __FUNCT__ "PetscProcessYAMLRPC" 1019 PetscErrorCode PetscProcessYAMLRPC(const char* request,char **result) 1020 { 1021 yaml_parser_t parser; 1022 yaml_event_t event; 1023 int done = 0; 1024 int count = 0; 1025 size_t len; 1026 PetscErrorCode ierr; 1027 PetscBool method,params,id; 1028 char *methodname,*idname,**args,**argso = 0; 1029 PetscInt argc = 0,argco,i; 1030 PetscErrorCode (*fun)(PetscInt,char **,PetscInt*,char ***); 1031 1032 PetscFunctionBegin; 1033 ierr = PetscMalloc(sizeof(char*),&args);CHKERRQ(ierr); 1034 yaml_parser_initialize(&parser); 1035 PetscStrlen(request,&len); 1036 yaml_parser_set_input_string(&parser, (unsigned char *)request, len); 1037 1038 /* this is totally bogus; it only handles the simple JSON-RPC messages */ 1039 while (!done) { 1040 if (!yaml_parser_parse(&parser, &event)) { 1041 ierr = PetscInfo(PETSC_NULL,"Found error in yaml/json\n");CHKERRQ(ierr); 1042 break; 1043 } 1044 done = (event.type == YAML_STREAM_END_EVENT); 1045 switch (event.type) { 1046 case YAML_STREAM_START_EVENT: 1047 ierr = PetscInfo(PETSC_NULL,"Stream start\n");CHKERRQ(ierr); 1048 break; 1049 case YAML_STREAM_END_EVENT: 1050 ierr = PetscInfo(PETSC_NULL,"Stream end\n");CHKERRQ(ierr); 1051 break; 1052 case YAML_DOCUMENT_START_EVENT: 1053 ierr = PetscInfo(PETSC_NULL,"Document start\n");CHKERRQ(ierr); 1054 break; 1055 case YAML_DOCUMENT_END_EVENT: 1056 ierr = PetscInfo(PETSC_NULL,"Document end\n");CHKERRQ(ierr); 1057 break; 1058 case YAML_MAPPING_START_EVENT: 1059 ierr = PetscInfo(PETSC_NULL,"Mapping start event\n");CHKERRQ(ierr); 1060 break; 1061 case YAML_MAPPING_END_EVENT: 1062 ierr = PetscInfo(PETSC_NULL,"Mapping end event \n");CHKERRQ(ierr); 1063 break; 1064 case YAML_ALIAS_EVENT: 1065 ierr = PetscInfo1(PETSC_NULL,"Alias event %s\n",event.data.alias.anchor);CHKERRQ(ierr); 1066 break; 1067 case YAML_SCALAR_EVENT: 1068 ierr = PetscInfo1(PETSC_NULL,"Scalar event %s\n",event.data.scalar.value);CHKERRQ(ierr); 1069 ierr = PetscStrcmp((char*)event.data.scalar.value,"method",&method);CHKERRQ(ierr); 1070 ierr = PetscStrcmp((char*)event.data.scalar.value,"params",¶ms);CHKERRQ(ierr); 1071 ierr = PetscStrcmp((char*)event.data.scalar.value,"id",&id);CHKERRQ(ierr); 1072 if (method) { 1073 yaml_event_delete(&event); 1074 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1075 ierr = PetscInfo1(PETSC_NULL,"Method %s\n",event.data.scalar.value);CHKERRQ(ierr); 1076 ierr = PetscStrallocpy((char*)event.data.scalar.value,&methodname);CHKERRQ(ierr); 1077 } else if (id) { 1078 yaml_event_delete(&event); 1079 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1080 ierr = PetscInfo1(PETSC_NULL,"Id %s\n",event.data.scalar.value);CHKERRQ(ierr); 1081 ierr = PetscStrallocpy((char*)event.data.scalar.value,&idname);CHKERRQ(ierr); 1082 } else if (params) { 1083 yaml_event_delete(&event); 1084 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1085 yaml_event_delete(&event); 1086 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1087 while (event.type != YAML_SEQUENCE_END_EVENT) { 1088 ierr = PetscInfo1(PETSC_NULL," Parameter %s\n",event.data.scalar.value);CHKERRQ(ierr); 1089 ierr = PetscStrallocpy((char*)event.data.scalar.value,&args[argc++]);CHKERRQ(ierr); 1090 yaml_event_delete(&event); 1091 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1092 } 1093 } else { /* ignore all the other variables in the mapping */ 1094 yaml_event_delete(&event); 1095 ierr = yaml_parser_parse(&parser, &event);CHKERRQ(!ierr); 1096 } 1097 break; 1098 case YAML_SEQUENCE_START_EVENT: 1099 ierr = PetscInfo(PETSC_NULL,"Sequence start event \n");CHKERRQ(ierr); 1100 break; 1101 case YAML_SEQUENCE_END_EVENT: 1102 ierr = PetscInfo(PETSC_NULL,"Sequence end event \n");CHKERRQ(ierr); 1103 break; 1104 default: 1105 /* It couldn't really happen. */ 1106 break; 1107 } 1108 1109 yaml_event_delete(&event); 1110 count ++; 1111 } 1112 yaml_parser_delete(&parser); 1113 1114 ierr = PetscDLLibrarySym(PETSC_COMM_SELF,PETSC_NULL,PETSC_NULL,methodname,(void**)&fun);CHKERRQ(ierr); 1115 if (fun) { 1116 ierr = PetscInfo1(PETSC_NULL,"Located function %s and running it\n",methodname);CHKERRQ(ierr); 1117 ierr = (*fun)(argc,args,&argco,&argso);CHKERRQ(ierr); 1118 } else { 1119 ierr = PetscInfo1(PETSC_NULL,"Did not locate function %s skipping it\n",methodname);CHKERRQ(ierr); 1120 } 1121 1122 for (i=0; i<argc; i++) { 1123 ierr = PetscFree(args[i]);CHKERRQ(ierr); 1124 } 1125 ierr = PetscFree(args);CHKERRQ(ierr); 1126 ierr = PetscFree(methodname);CHKERRQ(ierr); 1127 1128 /* convert the result back to YAML; should use YAML encoder, does not handle zero return arguments */ 1129 ierr = PetscMalloc(1024,result);CHKERRQ(ierr); 1130 ierr = PetscStrcpy(*result,"{\"error\": null, \"id\": \"");CHKERRQ(ierr); 1131 ierr = PetscStrcat(*result,idname);CHKERRQ(ierr); 1132 ierr = PetscStrcat(*result,"\", \"result\" : ");CHKERRQ(ierr); 1133 if (argco > 1) {ierr = PetscStrcat(*result,"[");CHKERRQ(ierr);} 1134 for (i=0; i<argco; i++) { 1135 ierr = PetscStrcat(*result,"\"");CHKERRQ(ierr); 1136 ierr = PetscStrcat(*result,argso[i]);CHKERRQ(ierr); 1137 ierr = PetscStrcat(*result,"\"");CHKERRQ(ierr); 1138 if (i < argco-1) {ierr = PetscStrcat(*result,",");CHKERRQ(ierr);} 1139 } 1140 if (argco > 1) {ierr = PetscStrcat(*result,"]");CHKERRQ(ierr);} 1141 ierr = PetscStrcat(*result,"}");CHKERRQ(ierr); 1142 ierr = PetscInfo1(PETSC_NULL,"YAML result of function %s\n",*result);CHKERRQ(ierr); 1143 1144 /* free work space */ 1145 ierr = PetscFree(idname);CHKERRQ(ierr); 1146 for (i=0; i<argco; i++) { 1147 ierr = PetscFree(argso[i]);CHKERRQ(ierr); 1148 } 1149 ierr = PetscFree(argso);CHKERRQ(ierr); 1150 PetscFunctionReturn(0); 1151 } 1152 #endif 1153 1154 #undef __FUNCT__ 1155 #define __FUNCT__ "PetscWebServeRequest" 1156 /*@C 1157 PetscWebServeRequest - serves a single web request 1158 1159 Not collective 1160 1161 Input Parameters: 1162 . port - the port 1163 1164 Level: developer 1165 1166 .seealso: PetscWebServe() 1167 @*/ 1168 PetscErrorCode PetscWebServeRequest(int port) 1169 { 1170 PetscErrorCode ierr; 1171 FILE *fd,*fdo; 1172 char buf[4096],fullpath[PETSC_MAX_PATH_LEN],truefullpath[PETSC_MAX_PATH_LEN]; 1173 char *method, *path, *protocol,*result; 1174 const char* type; 1175 PetscBool flg; 1176 PetscToken tok; 1177 PetscInt cnt = 8; 1178 1179 PetscFunctionBegin; 1180 fd = fdopen(port, "r+"); 1181 1182 ierr = PetscInfo(PETSC_NULL,"Processing web request\n");CHKERRQ(ierr); 1183 if (!fgets(buf, sizeof(buf), fd)) { 1184 ierr = PetscInfo(PETSC_NULL,"Cannot read web request, giving up\n");CHKERRQ(ierr); 1185 goto theend; 1186 } 1187 ierr = PetscInfo1(PETSC_NULL,"Processing web request %s",buf);CHKERRQ(ierr); 1188 1189 ierr = PetscTokenCreate(buf,' ',&tok);CHKERRQ(ierr); 1190 ierr = PetscTokenFind(tok,&method);CHKERRQ(ierr); 1191 ierr = PetscTokenFind(tok,&path);CHKERRQ(ierr); 1192 ierr = PetscTokenFind(tok,&protocol);CHKERRQ(ierr); 1193 1194 if (!method || !path || !protocol) { 1195 ierr = PetscInfo(PETSC_NULL,"Web request not well formatted, giving up\n");CHKERRQ(ierr); 1196 goto theend; 1197 } 1198 1199 ierr = PetscStrcmp(method,"GET",&flg); 1200 if (!flg) { 1201 #if defined(PETSC_HAVE_YAML) 1202 ierr = PetscStrcmp(method,"POST",&flg); 1203 /* 1204 Start to handle support for POSTs based on json-rpc 1205 */ 1206 if (flg) { 1207 int len; 1208 size_t elen; 1209 char *fnd; 1210 while (cnt--) { 1211 1212 if (!fgets(buf, sizeof(buf), fd)) { 1213 ierr = PetscInfo(PETSC_NULL,"Cannot read POST data, giving up\n");CHKERRQ(ierr); 1214 goto theend; 1215 } 1216 ierr = PetscInfo1(PETSC_NULL,"POSTED data %s",buf);CHKERRQ(ierr); 1217 ierr = PetscStrstr(buf,"Content-Type:",&fnd);CHKERRQ(ierr); 1218 if (fnd) { 1219 ierr = PetscStrstr(buf,"application/json-rpc",&fnd);CHKERRQ(ierr); 1220 if (!fnd) { 1221 ierr = PetscInfo(PETSC_NULL,"POST content is not json-rpc, skipping post\n");CHKERRQ(ierr); 1222 goto theend; 1223 } 1224 } 1225 } 1226 if (!fgets(buf, sizeof(buf), fd)) { 1227 ierr = PetscInfo(PETSC_NULL,"Cannot read POST length data, giving up\n");CHKERRQ(ierr); 1228 goto theend; 1229 } 1230 ierr = PetscInfo1(PETSC_NULL,"POSTED length data %s",buf);CHKERRQ(ierr); 1231 sscanf(buf,"Content-Length: %d\n",&len); 1232 ierr = PetscInfo1(PETSC_NULL,"Length of POSTED data %d\n",len);CHKERRQ(ierr); 1233 if (!fgets(buf, sizeof(buf), fd)) { 1234 ierr = PetscInfo(PETSC_NULL,"Cannot read POST data, giving up\n");CHKERRQ(ierr); 1235 goto theend; 1236 } 1237 ierr = PetscInfo1(PETSC_NULL,"POSTED data %s",buf);CHKERRQ(ierr); 1238 if (!fgets(buf, sizeof(buf), fd)) { 1239 ierr = PetscInfo(PETSC_NULL,"Cannot read POST data, giving up\n");CHKERRQ(ierr); 1240 goto theend; 1241 } 1242 ierr = PetscInfo1(PETSC_NULL,"POSTED data %s",buf);CHKERRQ(ierr); 1243 if (!fgets(buf, len+1, fd)) { /* why is this len + 1? */ 1244 ierr = PetscInfo(PETSC_NULL,"Cannot read POST data, giving up\n");CHKERRQ(ierr); 1245 goto theend; 1246 } 1247 ierr = PetscInfo1(PETSC_NULL,"POSTED data %s\n",buf);CHKERRQ(ierr); 1248 fseek(fd, 0, SEEK_CUR); /* Force change of stream direction */ 1249 ierr = PetscProcessYAMLRPC(buf,&result);CHKERRQ(ierr); 1250 ierr = PetscStrlen(result,&elen);CHKERRQ(ierr); 1251 ierr = PetscWebSendHeader(fd, 200, "OK", NULL, "application/json-rpc",(int)elen);CHKERRQ(ierr); 1252 fprintf(fd, "%s",result); 1253 goto theend; 1254 } else { 1255 #endif 1256 ierr = PetscWebSendError(fd, 501, "Not supported", NULL, "Method is not supported.");CHKERRQ(ierr); 1257 ierr = PetscInfo(PETSC_NULL,"Web request not a GET or POST, giving up\n");CHKERRQ(ierr); 1258 #if defined(PETSC_HAVE_YAML) 1259 } 1260 #endif 1261 } else { 1262 fseek(fd, 0, SEEK_CUR); /* Force change of stream direction */ 1263 1264 ierr = PetscStrcmp(path,"/favicon.ico",&flg);CHKERRQ(ierr); 1265 if (flg) { 1266 /* should have cool PETSc icon */; 1267 goto theend; 1268 } 1269 ierr = PetscStrcmp(path,"/",&flg);CHKERRQ(ierr); 1270 if (flg) { 1271 char program[128]; 1272 PetscMPIInt size; 1273 PetscViewer viewer; 1274 1275 ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); 1276 ierr = PetscGetProgramName(program,128);CHKERRQ(ierr); 1277 ierr = PetscWebSendHeader(fd, 200, "OK", NULL, "text/html", -1);CHKERRQ(ierr); 1278 fprintf(fd, "<HTML><HEAD><TITLE>Petsc Application Server</TITLE></HEAD>\r\n<BODY>"); 1279 fprintf(fd, "<H4>Serving PETSc application code %s </H4>\r\n\n",program); 1280 fprintf(fd, "Number of processes %d\r\n\n",size); 1281 fprintf(fd, "<HR>\r\n"); 1282 ierr = PetscViewerASCIIOpenWithFILE(PETSC_COMM_WORLD,fd,&viewer);CHKERRQ(ierr); 1283 ierr = PetscOptionsView(viewer);CHKERRQ(ierr); 1284 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 1285 fprintf(fd, "<HR>\r\n"); 1286 #if defined(PETSC_HAVE_AMS) 1287 if (PetscAMSPublishAll) { 1288 fprintf(fd, "<a href=\"./ams-tree\">Connect to Memory Snooper--Tree Display</a></p>\r\n\r\n"); 1289 fprintf(fd, "<a href=\"./ams-list\">Connect to Memory Snooper--List Display</a></p>\r\n\r\n"); 1290 } 1291 #endif 1292 fprintf(fd, "<a href=\"./AMSJavascript.html\">Connect to Memory Snooper--Interactive Javascript</a></p>\r\n\r\n"); 1293 ierr = PetscWebSendFooter(fd);CHKERRQ(ierr); 1294 goto theend; 1295 } 1296 1297 #if defined(PETSC_HAVE_AMS) 1298 ierr = PetscStrcmp(path,"/ams-list",&flg);CHKERRQ(ierr); 1299 if (flg) { 1300 ierr = PetscAMSDisplayList(fd);CHKERRQ(ierr); 1301 goto theend; 1302 } 1303 ierr = PetscInfo1(PETSC_NULL,"Browser path %s\n",path); 1304 ierr = PetscStrcmp(path,"/ams-tree",&flg);CHKERRQ(ierr); 1305 if (flg) { 1306 ierr = PetscAMSDisplayTree(fd);CHKERRQ(ierr); 1307 goto theend; 1308 } 1309 #endif 1310 ierr = PetscStrcpy(fullpath,"${PETSC_DIR}/include/web");CHKERRQ(ierr); 1311 ierr = PetscStrcat(fullpath,path);CHKERRQ(ierr); 1312 ierr = PetscInfo1(PETSC_NULL,"Checking for file %s\n",fullpath);CHKERRQ(ierr); 1313 ierr = PetscStrreplace(PETSC_COMM_SELF,fullpath,truefullpath,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 1314 fdo = fopen(truefullpath,"r"); 1315 if (fdo) { 1316 PetscInt length,index; 1317 char data[4096]; 1318 struct stat statbuf; 1319 int n; 1320 const char *suffixes[] = {".html",".js",".gif",0}, *mimes[] = {"text/html","text/javascript","image/gif","text/unknown"}; 1321 1322 ierr = PetscStrendswithwhich(fullpath,suffixes,&index);CHKERRQ(ierr); 1323 type = mimes[index]; 1324 if (!stat(truefullpath, &statbuf)) length = -1; 1325 else length = S_ISREG(statbuf.st_mode) ? statbuf.st_size : -1; 1326 ierr = PetscWebSendHeader(fd, 200, "OK", NULL, type, length);CHKERRQ(ierr); 1327 while ((n = fread(data, 1, sizeof(data), fdo)) > 0) fwrite(data, 1, n, fd); 1328 fclose(fdo); 1329 ierr = PetscInfo2(PETSC_NULL,"Sent file %s to browser using format %s\n",fullpath,type);CHKERRQ(ierr); 1330 goto theend; 1331 } 1332 ierr = PetscWebSendError(fd, 501, "Not supported", NULL, "Unknown request.");CHKERRQ(ierr); 1333 } 1334 theend: 1335 ierr = PetscTokenDestroy(&tok);CHKERRQ(ierr); 1336 fclose(fd); 1337 ierr = PetscInfo(PETSC_NULL,"Finished processing request\n");CHKERRQ(ierr); 1338 1339 PetscFunctionReturn(0); 1340 } 1341 1342 #undef __FUNCT__ 1343 #define __FUNCT__ "PetscWebServeWait" 1344 /*@C 1345 PetscWebServeWait - waits for requests on a thread 1346 1347 Not collective 1348 1349 Input Parameter: 1350 . port - port to listen on 1351 1352 Level: developer 1353 1354 .seealso: PetscViewerSocketOpen(), PetscWebServe() 1355 @*/ 1356 void *PetscWebServeWait(int *port) 1357 { 1358 PetscErrorCode ierr; 1359 int iport,listenport,tport = *port; 1360 1361 ierr = PetscInfo1(PETSC_NULL,"Starting webserver at port %d\n",tport);if (ierr) return 0; 1362 ierr = PetscFree(port);if (ierr) return 0; 1363 ierr = PetscSocketEstablish(tport,&listenport);if (ierr) return 0; 1364 while (1) { 1365 ierr = PetscSocketListen(listenport,&iport);if (ierr) return 0; 1366 ierr = PetscWebServeRequest(iport);if (ierr) return 0; 1367 close(iport); 1368 } 1369 close(listenport); 1370 return 0; 1371 } 1372 1373 #undef __FUNCT__ 1374 #define __FUNCT__ "PetscWebServe" 1375 /*@C 1376 PetscWebServe - start up the PETSc web server and respond to requests 1377 1378 Not collective - only does something on process zero of the communicator 1379 1380 Input Parameters: 1381 + comm - the MPI communicator 1382 - port - port to listen on 1383 1384 Options Database Key: 1385 + -server <port> - start PETSc webserver (default port is 8080) 1386 - -ams_publish_objects 1387 1388 1389 Notes: Point your browser to http://hostname:8080 to access the PETSc web server, where hostname is the name of your machine. 1390 If you are running PETSc on your local machine you can use http://localhost:8080 1391 1392 If the PETSc program completes before you connect with the browser you will not be able to connect to the PETSc webserver. 1393 1394 Read the top of $PETSC_DIR/include/web/AMSJavascript.py before running. 1395 1396 Level: developer 1397 1398 .seealso: PetscViewerSocketOpen() 1399 @*/ 1400 PetscErrorCode PetscWebServe(MPI_Comm comm,int port) 1401 { 1402 PetscErrorCode ierr; 1403 PetscMPIInt rank; 1404 pthread_t thread; 1405 int *trueport; 1406 1407 PetscFunctionBegin; 1408 if (port < 1 && port != PETSC_DEFAULT && port != PETSC_DECIDE) SETERRQ1(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,"Cannot use negative port number %d",port); 1409 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1410 if (rank) PetscFunctionReturn(0); 1411 1412 if (port == PETSC_DECIDE || port == PETSC_DEFAULT) port = 8080; 1413 ierr = PetscMalloc(1*sizeof(int),&trueport);CHKERRQ(ierr); /* malloc this so it still exists in thread */ 1414 *trueport = port; 1415 ierr = pthread_create(&thread, NULL, (void *(*)(void *))PetscWebServeWait, trueport);CHKERRQ(ierr); 1416 PetscFunctionReturn(0); 1417 } 1418 #endif 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433