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