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);