H i g h P e r f o r m a n c e S c r i p t S e r v e r B r o w s e r : W E B S e r v e r : A p p l i c a t i o n : : +-------------+ +-------------+ : +---------------+ : +-------------+ | | WWW client |==1==| HTTP server | : | FORTRAN | | +-------------+ : | client thread | : | application |-+ : +- - -(2)- - - -+ : +- - -(5)- - -+ | : | http_hpss_mst |==3==| hpss_share | | : |service thread |==4==| shr. image |-+ : +- - - - - - - -+ : +-------------+ Communication paths: 1. HTTP connection (TCP/IP port 80) initiated by client for url /$hpss/hpss_srv_xxx/... 2. Internal message-based communication path between thread servicing client connection and MST (Message-based Service Thread) thread. The communication over this pathway uses the normal OSU server's script prototol ( tags). 3. Service request mailbox, written by MST and read by application. The user application creates this mailbox during its initialization and the MST assigns a channel to it the first time a web client references the HPSS application. This is a directional mailbox, the connection fails if no application is present with a channel assigned to the mailbox. Each script invocation results in a single message being sent to the server request mailbox, the message contains: Output mailbox unit number. Input mailbox unit number (only if needed). Invocation method (HTBIN, CONVERT, etc). Request method (e.g. GET). CGI variable symbol table. Request content, (if room, if not input mailbox is supplied). 4. Output mailbox, written by application and read by MST. This is a directional mailbox, allowing the application to detect if MST disconnects due to error or web client disconnect. Each MST thread creates a unique output mailbox that is only used for 1 script invocation. 4a. Input mailbox. only created if needed to transfer MIME content included with the HTTP request. 5. HPSS_SHARE API (application programmer interface), which hides the complexities of the I/O with the web server behind a simple set of HPSS_* functions (initialize, accept, read, write, disconnect, getenv, getform). Programming model: The HPSS application runs continously in a dedicated process and has the following program structure: 1. Initialize (call HPSS_INITIALIZE('mailbox_name',hndl) ) 2. Wait for next request (HPSS_ACCEPT(hndl,subfunc)) 3. Produce CGI (Common Gateway Interfae) response based on CGI variables, form input, or other request content. (HPSS_GETENV(hndl,name,value,vlen), HPSS_WRITE(hndl,buffer,carcon), etc). 4. Disconnect (HPSS_DISCONNECT) and return to step 2. Note that is model is not multi-threaded, the HPSS application only logically deals with one client request at a time. Several aspects of the HPSS architecture should or can minimize the impact to the client: - The MST side (which is multi-threaded) reads any request content prior to notifying the application, meaning the application never has to wait on data from the client. - The output generated by the application (HPSS_WRITE) is written to the output mailbox asynchronously and buffered. The application can 'disconnect' and start processing the next request while the previous buffered output is still being drained back to the client. The number of these output streams that may be active at one time is the lesser of the MST's threadpol limit or 1/2 the app. processes ASTLM quota. - The application can create several instances of itself running in separate processes. The MST threads independantly write to the service request mailbox (and each has it's own output mailbox) so the multiple application instances will concurrently process the requests. Web server configuration: Since the web server side of HPSS is an MST, it is configured using the standard OSU configuration rules for MSTs, for example: service hpss pool=imap dynamic=(hpss,http_hpss_mst) info=hpss_srv_* exec /$hpss/* %hpss: suffix .hpss application/hpss presenation application/hpss %hpss:hpss_srv_preproc Application configuration: The HPSS application designer is responsible for providing for the application process creation and other configuration. Function descriptions: For all the functions, a STRING parameter is a character string passed by descriptor and an INTEGER parameter is a signed longword passed by reference. All functions return a VMS-style status integer (low bit set for success). hpss_initialize ( STRING mbx_logical, INTEGER mbx_type, INTEGER context ) This function initializes the hpss_share data structures and creates the service mailbox with the name specified by mbx_logical and in the table indicated by mbx_type. The context variable is initialized with a handle to be used as an input argument to the other hpss_share library calls. hpss_accept (INTEGER context, INTEGER timeout, INTEGER pid, STRING subfunc) This function waits for up to timeout seconds for the next script request to arrive from the web server or, if timeout is zero, wait untimed for the next script request. The pid argument receives the process ID of the requesting web server process (or one of its kernel threads). The subfunc argument receives the internal script invocation code, indicating the method used to invoke the script: HTBIN Requested URL matched an exec rule (i.e. /$hpss/). CONVERT Requested URL's suffix (e.g. dave.hpss) mapped to a presentation script. SEARCH The script was defined as the web servers search script. POST The script was named as the handler for an HTTP method (e.g. method put %hpss:hpss_srv_put). When a request arrives, hpss_accept initializes the CGI variable table and reads any accompanying request content into memory prior to returning. hpss_disconnect ( INTEGER context ) This function indicates the application is done processing the script request from the last hpss_accept() call. Any buffered output data is flushed the output stream is marked for rundown once the flush is complete. hpss_getenv ( INTEGER context, STRING name, STRING value, STRING length ) This function looks up the CGI variable (e.g. PATH_INFO) specified by the name argument and if found copies its value into value argument, truncating it or padding with spaces. The length argument receives the number of bytes actually copied from the variable value. Note that name argument does not have a prefix (WWW_) and is case sensitive. The special variable name %SYMBOL_LIST (note leading percent sign) will return a comma-separated list of the variables in the symbol table. hpss_getform (INTEGER context, STRING name, STRING value, STRING length) On the first call after an accept, this function builds a symbol table by parses the request content as form data. It then looks up symbol specified by the name argument and if found copies its value into the value argument, truncating it or padding with spaces. The length argument receives the number of bytes actually copied from the symbol value. Unlike hpss_getform, the name argument is NOT case sensitive. You cannot use this function and hpss_read on the same request. hpss_read ( INTEGER context, STRING buffer, INTEGER length ) This function returns the next piece of the saved request content to the caller in the buffer supplied. The length argument receives the number of data bytes copied. The content data is stream-oriented and raw, the buffer will contain any embedded record delimiters or content encoding. Caller should retrieve the value of the CONTENT_LENGTH variable to determine the total length needed to be read. hpss_write ( INTEGER context, STRING buffer, INTEGER flags ) This function sends the data sepecified by the buffer argument to web server, the data stream produced is interpreted by the web server as a standard CGI response - header lines terminated by a null line followed by data. The flags argument is a bit mask specifying arguments for the write: Bit 0 If set, causes a CR LF sequence (i.e. record delimter) to be appended to the output following the buffer data. This flag makes it so you can send a header line as HPSS_WRITE ( ctx, 'Content-type: text/plain', 1 ) without having to explicitly append the CR/LF. Bit 1 If set, forces buffered data to be flushed immediately to the web server and hence to the web client. You should only use this option if your application is doing server push type of operations. Note that the flush will only queue the data to be written, it will not Wrapper functions for 'C': Since string descriptors in C can be awkward to use, the hpss_share library also provides a set of wrapper functions to facilitate writing C-based HPSS applications. In general, string descriptors (STRING arguments) are replaced by null-terminated character strings if they are input parameters and a char pointer/in pair if they specify an output buffer. Note that the context argument is always passed as an INTEGER (int *). The prototypes for these functions are defined in hpss_share.h. The hpss_printf_c function is technically not a 'wrapper' since it provides functionality beyond passing it's arguments though to another function. int hpss_initialize_c ( char *mbx_logical, int mbx_type, INTEGER context ); // returns handle int hpss_accept_c ( INTEGER context, int timeout, INTEGER PID, // returns process ID. char *function, int func_size ); int hpss_getenv_c ( INTEGER context, char *name, char *value, int val_size, INTEGER ret_length ); int hpss_getform_c ( INTEGER context, char *name, char *value, int val_size, INTEGER ret_length ); int hpss_read_c ( INTEGER context, void *buffer, int bufsize, INTEGER ret_len); int hpss_write_c ( INTEGER context, void *buffer, int bufsize, int flags ); int hpss_printf_c ( INTEGER context, const char *fmt, ... );