You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by da...@apache.org on 2001/03/06 21:22:00 UTC

cvs commit: jakarta-tomcat/src/native/mod_jk/common jk_service.h

danmil      01/03/06 12:22:00

  Modified:    src/native/mod_jk/common jk_service.h
  Log:
  Extensive comments added to explain the structure of the core mod_jk
  classes.  Also explained how Shachor wrote object oriented code in C.
  
  Revision  Changes    Path
  1.4       +196 -9    jakarta-tomcat/src/native/mod_jk/common/jk_service.h
  
  Index: jk_service.h
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/native/mod_jk/common/jk_service.h,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- jk_service.h	2001/02/02 17:29:04	1.3
  +++ jk_service.h	2001/03/06 20:21:58	1.4
  @@ -58,7 +58,8 @@
    *              These are the web server (ws) the worker and the connection*
    *              JVM connection point                                       *
    * Author:      Gal Shachor <sh...@il.ibm.com>                           *
  - * Version:     $Revision: 1.3 $                                               *
  + *              Dan Milstein <da...@shore.net> 
  + * Version:     $Revision: 1.4 $                                               *
    ***************************************************************************/
   
   #ifndef JK_SERVICE_H
  @@ -72,7 +73,7 @@
   #ifdef __cplusplus
   extern "C" {
   #endif /* __cplusplus */
  -
  +    
   struct jk_ws_service;
   struct jk_endpoint;
   struct jk_worker;
  @@ -80,11 +81,49 @@
   typedef struct jk_endpoint   jk_endpoint_t;
   typedef struct jk_worker     jk_worker_t;
   
  +/*
  + * The web server service 'class'.  An instance of this class is created
  + * for each request which is forwarded from the web server to the servlet
  + * container.  Contains the basic information about the request
  + * (e.g. protocol, req_uri, etc), and also contains a series of methods
  + * which provide access to core web server functionality (start_response,
  + * read, write).  This class might be more accurately called ws_request.
  + *
  + * As with all the core jk classes, this is essentially an abstract base
  + * class which is implemented/extended by classes which are specific to a
  + * particular web server.  By using an abstract base class in this manner,
  + * workers can be written for different protocols (e.g. ajp12, ajp13)
  + * without the workers having to worry about which web server they are
  + * talking to.
  + *
  + * This particular OO-in-C system uses a 'ws_private' pointer to point to
  + * the platform-specific data.  So in the subclasses, the methods do most
  + * of their work by getting their hands on the ws_private pointer and then
  + * using that to get at the correctly formatted data and functions for
  + * their platform.
  + *
  + * Try imagining this as a 'public abstract class', and the ws_private
  + * pointer as a sort of extra 'this' reference.  Or imagine that you are
  + * seeing the internal vtables of your favorite OO language.  Whatever
  + * works for you.
  + *
  + * See apache1.3/mod_jk.c and iis/jk_isapi_plugin.c for examples.  
  + */
   struct jk_ws_service {
  +  
  +    /* 
  +     * A 'this' pointer which is used by the subclasses of this class to
  +     * point to data which is specific to a given web server platform
  +     * (e.g. Apache or IIS).  
  +     */
       void *ws_private;
       
       /*
  -     * Alive as long as the request is alive.
  +     * Provides memory management.  All data specific to this request is
  +     * allocated within this pool, which can then be reclaimed at the end
  +     * of the request handling cycle. 
  +     *
  +     * Alive as long as the request is alive.  
        */
       jk_pool_t *pool;
   
  @@ -155,8 +194,14 @@
       char    *jvm_route;
   
       /*
  -     * Callbacks into the web server.
  +     * Callbacks into the web server.  For each, the first argument is
  +     * essentially a 'this' pointer.  All return JK_TRUE on success
  +     * and JK_FALSE on failure.
        */
  +
  +    /*
  +     * Send the response headers to the browser.
  +     */
       int (JK_METHOD *start_response)(jk_ws_service_t *s,
                                       int status,
                                       const char *reason,
  @@ -164,48 +209,190 @@
                                       const char * const *header_values,
                                       unsigned num_of_headers);
   
  +    /*
  +     * Read a chunk of the request body into a buffer.  Attempt to read len
  +     * bytes into the buffer.  Write the number of bytes actually read into
  +     * actually_read.  
  +     */
       int (JK_METHOD *read)(jk_ws_service_t *s,
  -                          void *b,
  -                          unsigned l,
  -                          unsigned *a);
  +                          void *buffer,
  +                          unsigned len,
  +                          unsigned *actually_read);
   
  +    /*
  +     * Write a chunk of response data back to the browser.
  +     */
       int (JK_METHOD *write)(jk_ws_service_t *s,
  -                           const void *b,
  -                           unsigned l);
  +                           const void *buffer,
  +                           unsigned len);
   };
   
  +/*
  + * The endpoint 'class', which represents one end of a connection to the
  + * servlet engine.  Basically, supports nothing other than forwarding the
  + * request to the servlet engine.  Endpoints can be persistent (as with
  + * ajp13, where a single connection is reused many times), or can last for a
  + * single request (as with ajp12, where a new connection is created for
  + * every request).
  + *
  + * An endpoint for a given protocol is obtained by the web server plugin
  + * from a worker object for that protocol.  See below for details.
  + *
  + * As with all the core jk classes, this is essentially an abstract base
  + * class which is implemented/extended by classes which are specific to a
  + * particular protocol.  By using an abstract base class in this manner,
  + * plugins can be written for different servers (e.g. IIS, Apache) without
  + * the plugins having to worry about which protocol they are talking.
  + *
  + * This particular OO-in-C system uses a 'endpoint_private' pointer to
  + * point to the protocol-specific data/functions.  So in the subclasses, the
  + * methods do most of their work by getting their hands on the
  + * endpoint_private pointer and then using that to get at the functions for
  + * their protocol.
  + *
  + * Try imagining this as a 'public abstract class', and the
  + * endpoint_private pointer as a sort of extra 'this' reference.  Or
  + * imagine that you are seeing the internal vtables of your favorite OO
  + * language.  Whatever works for you.
  + *
  + * See jk_ajp13_worker.c and jk_ajp12_worker.c for examples.  
  + */
   struct jk_endpoint {
  +  
  +    /* 
  +     * A 'this' pointer which is used by the subclasses of this class to
  +     * point to data/functions which are specific to a given protocol 
  +     * (e.g. ajp12 or ajp13).  
  +     */
       void *endpoint_private;
   
  +    /*
  +     * Forward a request to the servlet engine.  The request is described
  +     * by the jk_ws_service_t object.  I'm not sure exactly how
  +     * is_recoverable_error is being used.  
  +     */
       int (JK_METHOD *service)(jk_endpoint_t *e, 
                                jk_ws_service_t *s,
                                jk_logger_t *l,
                                int *is_recoverable_error);
   
  +    /*
  +     * Called when this particular endpoint has finished processing a
  +     * request.  For some protocols (e.g. ajp12), this frees the memory
  +     * associated with the endpoint.  For others (e.g. ajp13), this can
  +     * return the endpoint to a cache of already opened endpoints.  
  +     *
  +     * Note that the first argument is *not* a 'this' pointer, but is
  +     * rather a pointer to a 'this' pointer.  This is necessary, because
  +     * we may need to free this object.
  +     */
       int (JK_METHOD *done)(jk_endpoint_t **p,
                             jk_logger_t *l);
   };
   
  +/*
  + * The worker 'class', which represents something to which the web server
  + * can delegate requests. 
  + *
  + * This can mean communicating with a particular servlet engine instance,
  + * using a particular protocol.  A single web server instance may have
  + * multiple workers communicating with a single servlet engine (it could be
  + * using ajp12 for some requests and ajp13 for others).  Or, a single web
  + * server instance could have multiple workers communicating with different
  + * servlet engines using the same protocol (it could be load balancing
  + * among many engines, using ajp13 for all communication).
  + *
  + * There is also a load balancing worker (jk_lb_worker.c), which itself
  + * manages a group of workers.
  + *
  + * Web servers are configured to forward requests to a given worker.  To
  + * handle those requests, the worker's get_endpoint method is called, and
  + * then the service() method of that endpoint is called.
  + *
  + * As with all the core jk classes, this is essentially an abstract base
  + * class which is implemented/extended by classes which are specific to a
  + * particular protocol (or request-handling system).  By using an abstract
  + * base class in this manner, plugins can be written for different servers
  + * (e.g. IIS, Apache) without the plugins having to worry about which
  + * protocol they are talking.
  + *
  + * This particular OO-in-C system uses a 'worker_private' pointer to
  + * point to the protocol-specific data/functions.  So in the subclasses, the
  + * methods do most of their work by getting their hands on the
  + * worker_private pointer and then using that to get at the functions for
  + * their protocol.
  + *
  + * Try imagining this as a 'public abstract class', and the
  + * worker_private pointer as a sort of extra 'this' reference.  Or
  + * imagine that you are seeing the internal vtables of your favorite OO
  + * language.  Whatever works for you.
  + *
  + * See jk_ajp13_worker.c and jk_ajp12_worker.c for examples.  
  + */
   struct jk_worker {
  +
  +    /* 
  +     * A 'this' pointer which is used by the subclasses of this class to
  +     * point to data/functions which are specific to a given protocol 
  +     * (e.g. ajp12 or ajp13).  
  +     */
       void *worker_private;
   
  +    /*
  +     * For all of the below (except destroy), the first argument is
  +     * essentially a 'this' pointer.  
  +     */
  +
  +    /*
  +     * Given a worker which is in the process of being created, and a list
  +     * of configuration options (or 'properties'), check to see if it the
  +     * options are.  This will always be called before the init() method.
  +     * The init/validate distinction is a bit hazy to me.
  +     * See jk_ajp13_worker.c and jk_worker.c->wc_create_worker() 
  +     */
       int (JK_METHOD *validate)(jk_worker_t *w,
                                 jk_map_t *props, 
                                 jk_logger_t *l);
   
  +    /*
  +     * Do whatever initialization needs to be done to start this worker up.
  +     * Configuration options are passed in via the props parameter.  
  +     */
       int (JK_METHOD *init)(jk_worker_t *w,
                             jk_map_t *props, 
                             jk_logger_t *l);
   
   
  +    /*
  +     * Obtain an endpoint to service a particular request.  A pointer to
  +     * the endpoint is stored in pend.  
  +     */
       int (JK_METHOD *get_endpoint)(jk_worker_t *w,
                                     jk_endpoint_t **pend,
                                     jk_logger_t *l);
   
  +    /*
  +     * Shutdown this worker.  The first argument is not a 'this' pointer,
  +     * but rather a pointer to 'this', so that the object can be free'd (I
  +     * think -- though that doesn't seem to be happening.  Hmmm).  
  +     */
       int (JK_METHOD *destroy)(jk_worker_t **w,
                                jk_logger_t *l);
   };
   
  +/*
  + * Essentially, an abstract base class (or factory class) with a single
  + * method -- think of it as createWorker() or the Factory Method Design
  + * Pattern.  There is a different worker_factory function for each of the
  + * different types of workers.  The set of all these functions is created
  + * at startup from the list in jk_worker_list.h, and then the correct one
  + * is chosen in jk_worker.c->wc_create_worker().  See jk_worker.c and
  + * jk_ajp13_worker.c for examples.
  + *
  + * This allows new workers to be written without modifing the plugin code
  + * for the various web servers (since the only link is through
  + * jk_worker_list.h).  
  + */
   typedef int (JK_METHOD *worker_factory)(jk_worker_t **w,
                                           const char *name,
                                           jk_logger_t *l);