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

Reply via email to