Brian Akins wrote:
Jim Jagielski wrote:
If this is data that needs to be accessed from "non-proxy" modules
then yes, I agree.
A basic API could look like. By worker, I am thinking about the mpm
sense, not the proxy sense. I guess "slot" may be a better term:
/*used for ap_scoreboard_do. mem is the memory associated with a
worker, data is what is passed to ap_scoreboard_do. pool is pool used
to create scoreboard*/
typedef apr_status_t ap_scoreboard_callback_fn_t(void* mem, void
*data, apr_pool_t *pool);
/*call the callback on all worker slots*/
AP_DECLARE(apr_status_t)ap_scoreboard_do(ap_scoreboard_t *s,
ap_scoreboard_callback_fn_t *func, void *data, apr_pool_t *pool);
/*create a new scoreboard with each item size is item_size. name is a
key used for debuggin and in mod_status output. This would create
shared memory, basically*/
AP_DECLARE(apr_status_t) ap_scoreboard_create(ap_scoreboard_t **new,
const char *name, apr_size_t item_size, apr_pool_t *pool);
/*get the memory associated with this worker slot. use c->id or c->sbh
to get offset into shared memory*/
AP_DECLARE(apr_status_t) ap_scoreboard_mem(ap_scoreboard_t *s,
conn_rec *c, void**mem);
Thoughts. Somthing very similar to this is used by several very busy
web sites...
Using the result of your ideas and the explaintions now I have mod_proxy
that uses the scoreboard via a "scoreboard" provider ;-)
Find enclosed the code.
Any comments?
The next step is to write shared memory scoreboard provider.
Cheers
Jean-Frederic
Index: mod_proxy_store_score.c
===================================================================
--- mod_proxy_store_score.c (revision 0)
+++ mod_proxy_store_score.c (revision 0)
@@ -0,0 +1,102 @@
+/* Copyright 1999-2006 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Comarea for the mod_proxy modules: This one uses the scoreboard */
+#define CORE_PRIVATE
+
+#include "mod_proxy.h"
+#include "mod_proxy_store.h"
+#include "ap_mpm.h"
+#include "scoreboard.h"
+
+struct ap_scoreboard {
+ void *ptr;
+ apr_size_t size;
+ int num;
+};
+
+static apr_status_t ap_scoreboard_do(ap_scoreboard_t *s,
ap_scoreboard_callback_fn_t *func, void *data, apr_pool_t *pool)
+{
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+ "ap_scoreboard_do");
+ return 0;
+}
+static apr_status_t ap_scoreboard_create(ap_scoreboard_t **new, const char
*name, apr_size_t item_size, int item_num, apr_pool_t *pool)
+{
+ void *score = NULL;
+ ap_scoreboard_t *res;
+
+#if PROXY_HAS_SCOREBOARD
+ if (ap_scoreboard_image) {
+ score = (void *)ap_get_scoreboard_lb(0);
+ if (!score)
+ return APR_ENOSHMAVAIL;
+ }
+#endif
+ if (!score)
+ score = apr_pcalloc(pool, item_size * item_num);
+ res = (ap_scoreboard_t *) apr_pcalloc(pool, sizeof(ap_scoreboard_t));
+ res->ptr = score;
+ res->size = item_size;
+ res->num = item_num;
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+ "ap_scoreboard_create");
+ *new = res;
+ return APR_SUCCESS;
+}
+static apr_status_t ap_scoreboard_mem(ap_scoreboard_t *score, int id,
void**mem)
+{
+
+ void *ptr = score->ptr + (score->size * id);
+#if PROXY_HAS_SCOREBOARD
+ if (ap_scoreboard_image)
+ score = (void *)ap_get_scoreboard_lb(id);
+#endif
+
+ if (!score)
+ return APR_ENOSHMAVAIL;
+ *mem = ptr;
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+ "ap_scoreboard_mem");
+ return APR_SUCCESS;
+}
+
+static const proxy_storage_method storage = {
+ &ap_scoreboard_do,
+ &ap_scoreboard_create,
+ &ap_scoreboard_mem
+};
+
+static void child_init(apr_pool_t *p, server_rec *s)
+{
+}
+
+static void ap_proxy_store_score_register_hook(apr_pool_t *p)
+{
+ ap_hook_child_init(child_init, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_register_provider(p, PROXY_STORAGE, "score", "0", &storage);
+}
+
+module AP_MODULE_DECLARE_DATA proxy_store_score_module = {
+ STANDARD20_MODULE_STUFF,
+ NULL, /* create per-directory config structure */
+ NULL, /* merge per-directory config structures */
+ NULL, /* create per-server config structure */
+ NULL, /* merge per-server config structures */
+ NULL, /* command apr_table_t */
+ ap_proxy_store_score_register_hook /* register hooks */
+};
+
Index: mod_proxy_store.h
===================================================================
--- mod_proxy_store.h (revision 0)
+++ mod_proxy_store.h (revision 0)
@@ -0,0 +1,58 @@
+#define MOD_PROXY_STORE_H
+/**
+ * @file mod_proxy_store.h
+ * @brief Proxy Extension Storage Module for Apache
+ *
+ * @defgroup MOD_PROXY mod_proxy
+ * @ingroup APACHE_MODS
+ * @{
+ */
+
+
+#define PROXY_STORAGE "proxystorage"
+
+typedef struct ap_scoreboard ap_scoreboard_t;
+
+/**
+ * callback function used for ap_scoreboard_do.
+ * @param mem is the memory associated with a worker.
+ * @param data is what is passed to ap_scoreboard_do.
+ * @param pool is pool used to create scoreboard
+ * @return APR_SUCCESS if all went well
+ */
+typedef apr_status_t ap_scoreboard_callback_fn_t(void* mem, void *data,
apr_pool_t *pool);
+
+struct proxy_storage_method {
+/**
+ * call the callback on all worker slots
+ * @param s ap_scoreboard_t to use.
+ * @param funct callback function to call for each element.
+ * @param data parameter for the callback function.
+ * @param pool is pool used to create scoreboard
+ * @return APR_SUCCESS if all went well
+ */
+AP_DECLARE(apr_status_t) (* ap_scoreboard_do)(ap_scoreboard_t *s,
ap_scoreboard_callback_fn_t *func, void *data, apr_pool_t *pool);
+
+/**
+ * create a new scoreboard with each item size is item_size.
+ * This would create shared memory, basically.
+ * @param pointer to store the address of the scoreboard.
+ * @param name is a key used for debugging and in mod_status output or allow
another process to share this space.
+ * @param item_size size of each idem
+ * @param item_num number of idem to create.
+ * @param pool is pool used to create scoreboard
+ * @return APR_SUCCESS if all went well
+ */
+AP_DECLARE(apr_status_t) (* ap_scoreboard_create)(ap_scoreboard_t **new, const
char *name, apr_size_t item_size, int item_num, apr_pool_t *pool);
+
+/**
+ * get the memory associated with this worker slot.
+ * @param s ap_scoreboard_t to use.
+ * @param item_id item to return for 0 to item_num
+ * @param mem address to store the pointer to the slot
+ * @return APR_SUCCESS if all went well
+ */
+AP_DECLARE(apr_status_t) (* ap_scoreboard_mem)(ap_scoreboard_t *s, int
item_id, void**mem);
+};
+
+typedef struct proxy_storage_method proxy_storage_method;
Index: config.m4
===================================================================
--- config.m4 (revision 421342)
+++ config.m4 (working copy)
@@ -19,6 +19,7 @@
proxy_fcgi_objs="mod_proxy_fcgi.lo"
proxy_ajp_objs="mod_proxy_ajp.lo ajp_header.lo ajp_link.lo ajp_msg.lo"
proxy_balancer_objs="mod_proxy_balancer.lo"
+proxy_store_score="mod_proxy_store_score.lo"
case "$host" in
*os2*)
@@ -39,6 +40,7 @@
APACHE_MODULE(proxy_fcgi, Apache proxy FastCGI module, $proxy_fcgi_objs, ,
$proxy_mods_enable)
APACHE_MODULE(proxy_ajp, Apache proxy AJP module, $proxy_ajp_objs, ,
$proxy_mods_enable)
APACHE_MODULE(proxy_balancer, Apache proxy BALANCER module,
$proxy_balancer_objs, , $proxy_mods_enable)
+APACHE_MODULE(proxy_store_score, Apache proxy score board storage module,
$proxy_store_score_objs, , $proxy_mods_enable)
APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/$modpath_current/../generators])
Index: proxy_util.c
===================================================================
--- proxy_util.c (revision 421342)
+++ proxy_util.c (working copy)
@@ -15,9 +15,15 @@
*/
/* Utility routines for Apache proxy */
+
+#define JFCNEW 1
#include "mod_proxy.h"
+#ifdef JFCNEW
+#include "mod_proxy_store.h"
+#else
+#include "scoreboard.h"
+#endif
#include "ap_mpm.h"
-#include "scoreboard.h"
#include "apr_version.h"
#if APR_HAVE_UNISTD_H
@@ -1599,6 +1605,16 @@
proxy_worker *worker,
server_rec *s)
{
+#ifdef JFCNEW
+ void *score = NULL;
+ ap_scoreboard_t *myscore;
+ if (worker->context) {
+ proxy_storage_method *store = (proxy_storage_method *) worker->context;
+ /* XXX: I probably want to be able to a big size than
sizeof(proxy_worker_stat) and more worker than proxy_lb_workers */
+ store->ap_scoreboard_create(&myscore, "proxy comarea",
sizeof(proxy_worker_stat), proxy_lb_workers, conf->pool);
+ store->ap_scoreboard_mem(myscore, worker->id, &score);
+ }
+#else
#if PROXY_HAS_SCOREBOARD
lb_score *score = NULL;
#else
@@ -1628,6 +1644,7 @@
}
}
#endif
+#endif
if (!score) {
score = apr_pcalloc(conf->pool, sizeof(proxy_worker_stat));
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
Index: mod_proxy.c
===================================================================
--- mod_proxy.c (revision 421342)
+++ mod_proxy.c (working copy)
@@ -17,6 +17,7 @@
#define CORE_PRIVATE
#include "mod_proxy.h"
+#include "mod_proxy_store.h"
#include "mod_core.h"
#include "apr_optional.h"
#include "scoreboard.h"
@@ -38,6 +39,11 @@
#endif
/*
+ * Storage for the comarea
+ */
+static const proxy_storage_method *storage = NULL;
+
+/*
* A Web proxy module. Stages:
*
* translate_name: set filename to proxy:<URL>
@@ -1075,6 +1081,14 @@
const char *err = ap_proxy_add_worker(&worker, cmd->pool, conf, r);
if (err)
return apr_pstrcat(cmd->temp_pool, "ProxyPass ", err, NULL);
+ if (storage) {
+ worker->context = (void *) storage;
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+ "add_pass: storage %d", storage);
+ }
+ else
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+ "add_pass: storage NULL");
} else {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
"worker %s already used by another worker",
worker->name);
@@ -1475,6 +1489,14 @@
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
"worker %s already used by another worker",
worker->name);
}
+ if (storage) {
+ worker->context = (void *) storage;
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+ "add_member: storage %d", storage);
+ }
+ else
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+ "add_member: storage NULL");
PROXY_COPY_CONF_PARAMS(worker, conf);
arr = apr_table_elts(params);
@@ -1911,6 +1933,13 @@
APR_HOOK_MIDDLE);
/* Reset workers count on gracefull restart */
proxy_lb_workers = 0;
+ storage = ap_lookup_provider(PROXY_STORAGE, "score", "0");
+ if (storage)
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+ "proxy_pre_config: storage %d", storage);
+ else
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+ "proxy_pre_config: storage NULL");
return OK;
}