On 12/23/2008 07:39 PM, [email protected] wrote: > Author: jim > Date: Tue Dec 23 10:39:56 2008 > New Revision: 729059 > > URL: http://svn.apache.org/viewvc?rev=729059&view=rev > Log: > Add in the useful slotmem memory module, from httpd-scoreboard. > Cleaned up... > > Added: > httpd/httpd/trunk/modules/mem/ > httpd/httpd/trunk/modules/mem/.deps > httpd/httpd/trunk/modules/mem/Makefile (with props) > httpd/httpd/trunk/modules/mem/Makefile.in (with props) > httpd/httpd/trunk/modules/mem/config5.m4 (with props) > httpd/httpd/trunk/modules/mem/mod_plainmem.c (with props) > httpd/httpd/trunk/modules/mem/mod_sharedmem.c (with props) > httpd/httpd/trunk/modules/mem/modules.mk > httpd/httpd/trunk/modules/mem/sharedmem_util.c (with props) > httpd/httpd/trunk/modules/mem/sharedmem_util.h (with props) > httpd/httpd/trunk/modules/mem/slotmem.h (with props) > > Added: httpd/httpd/trunk/modules/mem/.deps > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/mem/.deps?rev=729059&view=auto > ============================================================================== > (empty) > > Added: httpd/httpd/trunk/modules/mem/Makefile > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/mem/Makefile?rev=729059&view=auto > ============================================================================== > --- httpd/httpd/trunk/modules/mem/Makefile (added) > +++ httpd/httpd/trunk/modules/mem/Makefile Tue Dec 23 10:39:56 2008 > @@ -0,0 +1,7 @@ > +top_srcdir = /Users/jim/src/asf/code/dev/httpd-trunk > +top_builddir = /Users/jim/src/asf/code/dev/httpd-trunk > +srcdir = /Users/jim/src/asf/code/dev/httpd-trunk/modules/mem > +builddir = /Users/jim/src/asf/code/dev/httpd-trunk/modules/mem > +VPATH = /Users/jim/src/asf/code/dev/httpd-trunk/modules/mem > + > +include $(top_srcdir)/build/special.mk > > Propchange: httpd/httpd/trunk/modules/mem/Makefile > ------------------------------------------------------------------------------ > svn:eol-style = native
I deleted the above two files / dirs in r729080 as they get generated during build. > > > Added: httpd/httpd/trunk/modules/mem/config5.m4 > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/mem/config5.m4?rev=729059&view=auto > ============================================================================== > --- httpd/httpd/trunk/modules/mem/config5.m4 (added) > +++ httpd/httpd/trunk/modules/mem/config5.m4 Tue Dec 23 10:39:56 2008 > @@ -0,0 +1,14 @@ > +dnl modules enabled in this directory by default > + > +dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, > config]]]]) > + > +APACHE_MODPATH_INIT(mem) > + > +sharedmem_objs="mod_sharedmem.lo sharedmem_util.lo" > +APACHE_MODULE(sharedmem, memslot provider that uses shared memory, > $sharedmem_objs, , most) > +APACHE_MODULE(plainmem, memslot provider that uses plain memory, , , no) > + > +# Ensure that other modules can pick up slotmem.h > +APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/$modpath_current]) Hm. I think this should be in includes if it is intended to be used by other stock modules and at least it needs to be copied to includes during installation. > + > +APACHE_MODPATH_FINISH > > Propchange: httpd/httpd/trunk/modules/mem/config5.m4 > ------------------------------------------------------------------------------ > svn:eol-style = native > > Added: httpd/httpd/trunk/modules/mem/mod_plainmem.c > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/mem/mod_plainmem.c?rev=729059&view=auto > ============================================================================== > --- httpd/httpd/trunk/modules/mem/mod_plainmem.c (added) > +++ httpd/httpd/trunk/modules/mem/mod_plainmem.c Tue Dec 23 10:39:56 2008 > +static apr_status_t ap_slotmem_create(ap_slotmem_t **new, const char *name, > apr_size_t item_size, int item_num, apr_pool_t *pool) > +{ > + void *slotmem = NULL; > + ap_slotmem_t *res; > + ap_slotmem_t *next = globallistmem; > + const char *fname; > + apr_status_t rv; > + > + if (name) { > + if (name[0] == ':') > + fname = name; > + else > + fname = ap_server_root_relative(pool, name); > + > + /* first try to attach to existing slotmem */ > + if (next) { > + for (;;) { > + if (strcmp(next->name, fname) == 0) { > + /* we already have it */ > + *new = next; > + return APR_SUCCESS; > + } > + if (!next->next) > + break; > + next = next->next; > + } > + } > + } else > + fname = "anonymous"; > + > + /* create the memory using the globalpool */ > + res = (ap_slotmem_t *) apr_pcalloc(globalpool, sizeof(ap_slotmem_t)); > + res->base = apr_pcalloc(globalpool, item_size * item_num); > + if (!res->base) > + return APR_ENOSHMAVAIL; > + > + /* For the chained slotmem stuff */ > + res->name = apr_pstrdup(globalpool, fname); > + res->size = item_size; > + res->num = item_num; > + res->next = NULL; > + if (globallistmem==NULL) > + globallistmem = res; > + else > + next->next = res; Style! Why no stack approach, but a queue approach for the list? > + > + *new = res; > + return APR_SUCCESS; > +} This function is not thread safe. Is it only intended to be called during phases where there aren't multiple threads? If yes, a warning in the documentation would be cool. > +static apr_status_t ap_slotmem_mem(ap_slotmem_t *score, int id, void**mem) > +{ > + > + void *ptr; > + > + if (!score) > + return APR_ENOSHMAVAIL; > + if (id<0 || id>score->num) > + return APR_ENOSHMAVAIL; Style! > + > + ptr = score->base + score->size * id; > + if (!ptr) > + return APR_ENOSHMAVAIL; > + *mem = ptr; > + return APR_SUCCESS; > +} > + > Added: httpd/httpd/trunk/modules/mem/mod_sharedmem.c > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/mem/mod_sharedmem.c?rev=729059&view=auto > ============================================================================== > --- httpd/httpd/trunk/modules/mem/mod_sharedmem.c (added) > +++ httpd/httpd/trunk/modules/mem/mod_sharedmem.c Tue Dec 23 10:39:56 2008 > @@ -0,0 +1,72 @@ > +/* Licensed to the Apache Software Foundation (ASF) under one or more > + * contributor license agreements. See the NOTICE file distributed with > + * this work for additional information regarding copyright ownership. > + * The ASF licenses this file to You 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. > + */ > + > +/* Memory handler for a shared memory divided in slot. > + * This one uses shared memory. > + */ > +#define CORE_PRIVATE > + > +#include "apr.h" > +#include "apr_pools.h" > +#include "apr_shm.h" > + > +#include "httpd.h" > +#include "http_config.h" > +#include "http_log.h" > + > +#include "slotmem.h" > +#include "sharedmem_util.h" > + > +/* make sure the shared memory is cleaned */ > +static int initialize_cleanup(apr_pool_t *p, apr_pool_t *plog, apr_pool_t > *ptemp, server_rec *s) > +{ > + sharedmem_initialize_cleanup(p); > + return OK; > +} > + > +static int pre_config(apr_pool_t *p, apr_pool_t *plog, > + apr_pool_t *ptemp) > +{ > + apr_pool_t *global_pool; > + apr_status_t rv; > + > + rv = apr_pool_create(&global_pool, NULL); > + if (rv != APR_SUCCESS) { > + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, > + "Fatal error: unable to create global pool for shared > slotmem"); > + return rv; > + } > + sharedmem_initglobalpool(global_pool); > + return OK; > +} > + > +static void ap_sharedmem_register_hook(apr_pool_t *p) > +{ > + const slotmem_storage_method *storage = sharedmem_getstorage(); > + ap_register_provider(p, SLOTMEM_STORAGE, "shared", "0", storage); > + ap_hook_post_config(initialize_cleanup, NULL, NULL, APR_HOOK_LAST); > + ap_hook_pre_config(pre_config, NULL, NULL, APR_HOOK_MIDDLE); > +} > + > +module AP_MODULE_DECLARE_DATA sharedmem_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_sharedmem_register_hook /* register hooks */ > +}; > > Propchange: httpd/httpd/trunk/modules/mem/mod_sharedmem.c > ------------------------------------------------------------------------------ > svn:eol-style = native > > Added: httpd/httpd/trunk/modules/mem/modules.mk > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/mem/modules.mk?rev=729059&view=auto > ============================================================================== > --- httpd/httpd/trunk/modules/mem/modules.mk (added) > +++ httpd/httpd/trunk/modules/mem/modules.mk Tue Dec 23 10:39:56 2008 > @@ -0,0 +1,5 @@ > +libmod_sharedmem.la: mod_sharedmem.lo sharedmem_util.lo > + $(MOD_LINK) mod_sharedmem.lo sharedmem_util.lo $(MOD_SHAREDMEM_LDADD) > +DISTCLEAN_TARGETS = modules.mk > +static = libmod_sharedmem.la > +shared = > > Added: httpd/httpd/trunk/modules/mem/sharedmem_util.c > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/mem/sharedmem_util.c?rev=729059&view=auto > ============================================================================== > --- httpd/httpd/trunk/modules/mem/sharedmem_util.c (added) > +++ httpd/httpd/trunk/modules/mem/sharedmem_util.c Tue Dec 23 10:39:56 2008 > @@ -0,0 +1,376 @@ > +/* Licensed to the Apache Software Foundation (ASF) under one or more > + * contributor license agreements. See the NOTICE file distributed with > + * this work for additional information regarding copyright ownership. > + * The ASF licenses this file to You 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. > + */ > + > +/* Memory handler for a shared memory divided in slot. > + * This one uses shared memory. > + */ > +#define CORE_PRIVATE > + > +#include "apr.h" > +#include "apr_file_io.h" > +#include "apr_strings.h" > +#include "apr_pools.h" > +#include "apr_shm.h" > + > +#include "httpd.h" > +#include "http_config.h" > +#include "http_log.h" > + > +#include "slotmem.h" > +#include "sharedmem_util.h" > + > +/* The description of the slots to reuse the slotmem */ > +struct sharedslotdesc { > + apr_size_t item_size; > + int item_num; > +}; > + > +struct ap_slotmem { > + char *name; > + apr_shm_t *shm; > + void *base; > + apr_size_t size; > + int num; > + apr_pool_t *globalpool; Why storing the pool here again if the same is available via a static variable? > + struct ap_slotmem *next; > +}; > + > +/* global pool and list of slotmem we are handling */ > +static struct ap_slotmem *globallistmem = NULL; > +static apr_pool_t *globalpool = NULL; > + > +/* > + * Persiste the slotmem in a file > + * slotmem name and file name. > + * anonymous : $server_root/logs/anonymous.slotmem > + * :module.c : $server_root/logs/module.c.slotmem > + * abs_name : $abs_name.slotmem > + * > + */ > +static const char *store_filename(apr_pool_t *pool, const char *slotmemname) > +{ > + const char *storename; > + const char *fname; > + if (strcmp(slotmemname, "anonymous") == 0) > + fname = ap_server_root_relative(pool, "logs/anonymous"); Hm. Hardcoded relative location? This looks ugly. > + else if (slotmemname[0] == ':') { > + const char *tmpname; > + tmpname = apr_pstrcat(pool, "logs/", &slotmemname[1], NULL); > + fname = ap_server_root_relative(pool, tmpname); > + } > + else { > + fname = slotmemname; > + } > + storename = apr_pstrcat(pool, fname , ".slotmem", NULL); > + return storename; > +} > + > +static apr_status_t ap_slotmem_do(ap_slotmem_t *mem, > ap_slotmem_callback_fn_t *func, void *data, apr_pool_t *pool) > +{ > + int i; > + void *ptr; > + > + if (!mem) { > + return APR_ENOSHMAVAIL; > + } > + > + ptr = mem->base; > + for (i = 0; i < mem->num; i++) { > + ptr = ptr + mem->size; > + func((void *)ptr, data, pool); > + } > + return 0; Why not APR_SUCCESS? > +} > +static apr_status_t ap_slotmem_create(ap_slotmem_t **new, const char *name, > apr_size_t item_size, int item_num, apr_pool_t *pool) > +{ > +/* void *slotmem = NULL; */ > + void *ptr; > + struct sharedslotdesc desc; > + ap_slotmem_t *res; > + ap_slotmem_t *next = globallistmem; > + const char *fname; > + apr_status_t rv; > + > + if (globalpool == NULL) > + return APR_ENOSHMAVAIL; > + if (name) { > + if (name[0] == ':') { > + fname = name; > + } > + else { > + fname = ap_server_root_relative(pool, name); > + } > + > + /* first try to attach to existing slotmem */ > + if (next) { > + for (;;) { > + if (strcmp(next->name, fname) == 0) { > + /* we already have it */ > + *new = next; > + return APR_SUCCESS; > + } > + if (!next->next) { > + break; > + } > + next = next->next; > + } > + } > + } > + else { > + fname = "anonymous"; > + } > + > + /* first try to attach to existing shared memory */ > + res = (ap_slotmem_t *) apr_pcalloc(globalpool, sizeof(ap_slotmem_t)); > + if (name && name[0] != ':') { > + rv = apr_shm_attach(&res->shm, fname, globalpool); > + } > + else { > + rv = APR_EINVAL; > + } > + if (rv == APR_SUCCESS) { > + /* check size */ > + if (apr_shm_size_get(res->shm) != item_size * item_num + > sizeof(struct sharedslotdesc)) { > + apr_shm_detach(res->shm); > + res->shm = NULL; > + return APR_EINVAL; > + } > + ptr = apr_shm_baseaddr_get(res->shm); > + memcpy(&desc, ptr, sizeof(desc)); > + if ( desc.item_size != item_size || desc.item_num != item_num) { > + apr_shm_detach(res->shm); > + res->shm = NULL; > + return APR_EINVAL; > + } > + ptr = ptr + sizeof(desc); > + } > + else { > + if (name && name[0] != ':') { > + apr_shm_remove(fname, globalpool); > + rv = apr_shm_create(&res->shm, item_size * item_num + > sizeof(struct sharedslotdesc), fname, globalpool); > + } > + else { > + rv = apr_shm_create(&res->shm, item_size * item_num + > sizeof(struct sharedslotdesc), NULL, globalpool); > + } > + if (rv != APR_SUCCESS) { > + return rv; > + } > + ptr = apr_shm_baseaddr_get(res->shm); > + desc.item_size = item_size; > + desc.item_num = item_num; > + memcpy(ptr, &desc, sizeof(desc)); > + ptr = ptr + sizeof(desc); > + memset(ptr, 0, item_size * item_num); > + restore_slotmem(ptr, fname, item_size, item_num, pool); If item_size and item_num do not match with what is saved the caller gets not notified that something bad happened. > + } > + > + /* For the chained slotmem stuff */ > + res->name = apr_pstrdup(globalpool, fname); > + res->base = ptr; > + res->size = item_size; > + res->num = item_num; > + res->globalpool = globalpool; > + res->next = NULL; > + if (globallistmem==NULL) { > + globallistmem = res; > + } > + else { > + next->next = res; > + } Why no stack approach, but a queue approach for the list? > + > + *new = res; > + return APR_SUCCESS; > +} > +static apr_status_t ap_slotmem_attach(ap_slotmem_t **new, const char *name, > apr_size_t *item_size, int *item_num, apr_pool_t *pool) > +{ > +/* void *slotmem = NULL; */ > + void *ptr; > + ap_slotmem_t *res; > + ap_slotmem_t *next = globallistmem; > + struct sharedslotdesc desc; > + const char *fname; > + apr_status_t rv; > + > + if (globalpool == NULL) { > + return APR_ENOSHMAVAIL; > + } > + if (name) { > + if (name[0] == ':') { > + fname = name; > + } > + else { > + fname = ap_server_root_relative(pool, name); > + } > + } > + else { > + return APR_ENOSHMAVAIL; > + } > + > + /* first try to attach to existing slotmem */ > + if (next) { > + for (;;) { > + if (strcmp(next->name, fname) == 0) { > + /* we already have it */ > + *new = next; > + *item_size = next->size; > + *item_num = next->num; > + return APR_SUCCESS; > + } > + if (!next->next) > + break; > + next = next->next; > + } > + } > + > + /* first try to attach to existing shared memory */ > + res = (ap_slotmem_t *) apr_pcalloc(globalpool, sizeof(ap_slotmem_t)); > + rv = apr_shm_attach(&res->shm, fname, globalpool); > + if (rv != APR_SUCCESS) { > + return rv; > + } > + > + /* Read the description of the slotmem */ > + ptr = apr_shm_baseaddr_get(res->shm); > + memcpy(&desc, ptr, sizeof(desc)); > + ptr = ptr + sizeof(desc); > + > + /* For the chained slotmem stuff */ > + res->name = apr_pstrdup(globalpool, fname); > + res->base = ptr; > + res->size = desc.item_size; > + res->num = desc.item_num; > + res->globalpool = globalpool; > + res->next = NULL; > + if (globallistmem==NULL) { > + globallistmem = res; > + } > + else { > + next->next = res; > + } Why no stack approach, but a queue approach for the list? > + > + *new = res; > + *item_size = desc.item_size; > + *item_num = desc.item_num; > + return APR_SUCCESS; > +} > +static apr_status_t ap_slotmem_mem(ap_slotmem_t *score, int id, void**mem) > +{ > + > + void *ptr; > + > + if (!score) { > + return APR_ENOSHMAVAIL; > + } > + if (id<0 || id>score->num) { > + return APR_ENOSHMAVAIL; > + } > + > + ptr = score->base + score->size * id; > + if (!ptr) { > + return APR_ENOSHMAVAIL; > + } > + ptr = score->base + score->size * id; Why calculating ptr twice? > + *mem = ptr; > + return APR_SUCCESS; > +} > + Regards RĂ¼diger
