diff options
Diffstat (limited to 'modules/slotmem/mod_slotmem_plain.c')
-rw-r--r-- | modules/slotmem/mod_slotmem_plain.c | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/modules/slotmem/mod_slotmem_plain.c b/modules/slotmem/mod_slotmem_plain.c new file mode 100644 index 0000000..4c2b19b --- /dev/null +++ b/modules/slotmem/mod_slotmem_plain.c @@ -0,0 +1,343 @@ +/* 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 plain memory divided in slot. + * This one uses plain memory. + */ + +#include "ap_slotmem.h" + +#define AP_SLOTMEM_IS_PREGRAB(t) (t->type & AP_SLOTMEM_TYPE_PREGRAB) + +struct ap_slotmem_instance_t { + char *name; /* per segment name */ + void *base; /* data set start */ + apr_size_t size; /* size of each memory slot */ + unsigned int num; /* number of mem slots */ + apr_pool_t *gpool; /* per segment global pool */ + char *inuse; /* in-use flag table*/ + ap_slotmem_type_t type; /* type-specific flags */ + struct ap_slotmem_instance_t *next; /* location of next allocated segment */ +}; + + +/* global pool and list of slotmem we are handling */ +static struct ap_slotmem_instance_t *globallistmem = NULL; +static apr_pool_t *gpool = NULL; + +static apr_status_t slotmem_do(ap_slotmem_instance_t *mem, ap_slotmem_callback_fn_t *func, void *data, apr_pool_t *pool) +{ + unsigned int i; + char *ptr; + char *inuse; + apr_status_t retval = APR_SUCCESS; + + + if (!mem) + return APR_ENOSHMAVAIL; + + ptr = (char *)mem->base; + inuse = mem->inuse; + for (i = 0; i < mem->num; i++, inuse++) { + if (!AP_SLOTMEM_IS_PREGRAB(mem) || + (AP_SLOTMEM_IS_PREGRAB(mem) && *inuse)) { + retval = func((void *) ptr, data, pool); + if (retval != APR_SUCCESS) + break; + } + ptr += mem->size; + } + return retval; +} + +static apr_status_t slotmem_create(ap_slotmem_instance_t **new, const char *name, apr_size_t item_size, unsigned int item_num, ap_slotmem_type_t type, apr_pool_t *pool) +{ + ap_slotmem_instance_t *res; + ap_slotmem_instance_t *next = globallistmem; + apr_size_t basesize = (item_size * item_num); + + const char *fname; + + if (name) { + if (name[0] == ':') + fname = name; + else + fname = ap_runtime_dir_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 gpool */ + res = (ap_slotmem_instance_t *) apr_pcalloc(gpool, sizeof(ap_slotmem_instance_t)); + res->base = apr_pcalloc(gpool, basesize + (item_num * sizeof(char))); + if (!res->base) + return APR_ENOSHMAVAIL; + + /* For the chained slotmem stuff */ + res->name = apr_pstrdup(gpool, fname); + res->size = item_size; + res->num = item_num; + res->next = NULL; + res->type = type; + res->inuse = (char *)res->base + basesize; + if (globallistmem == NULL) + globallistmem = res; + else + next->next = res; + + *new = res; + return APR_SUCCESS; +} + +static apr_status_t slotmem_attach(ap_slotmem_instance_t **new, const char *name, apr_size_t *item_size, unsigned int *item_num, apr_pool_t *pool) +{ + ap_slotmem_instance_t *next = globallistmem; + const char *fname; + + if (name) { + if (name[0] == ':') + fname = name; + else + fname = ap_runtime_dir_relative(pool, name); + } + else + return APR_ENOSHMAVAIL; + + /* first try to attach to existing slotmem */ + while (next) { + if (strcmp(next->name, fname) == 0) { + /* we already have it */ + *new = next; + *item_size = next->size; + *item_num = next->num; + return APR_SUCCESS; + } + next = next->next; + } + + return APR_ENOSHMAVAIL; +} + +static apr_status_t slotmem_dptr(ap_slotmem_instance_t *score, unsigned int id, void **mem) +{ + + char *ptr; + + if (!score) + return APR_ENOSHMAVAIL; + if (id >= score->num) + return APR_EINVAL; + + ptr = (char *)score->base + score->size * id; + if (!ptr) + return APR_ENOSHMAVAIL; + *mem = ptr; + return APR_SUCCESS; +} + +static apr_status_t slotmem_get(ap_slotmem_instance_t *slot, unsigned int id, unsigned char *dest, apr_size_t dest_len) +{ + void *ptr; + char *inuse; + apr_status_t ret; + + if (!slot) { + return APR_ENOSHMAVAIL; + } + + inuse = slot->inuse + id; + if (id >= slot->num) { + return APR_EINVAL; + } + if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) { + return APR_NOTFOUND; + } + ret = slotmem_dptr(slot, id, &ptr); + if (ret != APR_SUCCESS) { + return ret; + } + *inuse=1; + memcpy(dest, ptr, dest_len); /* bounds check? */ + return APR_SUCCESS; +} + +static apr_status_t slotmem_put(ap_slotmem_instance_t *slot, unsigned int id, unsigned char *src, apr_size_t src_len) +{ + void *ptr; + char *inuse; + apr_status_t ret; + + if (!slot) { + return APR_ENOSHMAVAIL; + } + + inuse = slot->inuse + id; + if (id >= slot->num) { + return APR_EINVAL; + } + if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) { + return APR_NOTFOUND; + } + ret = slotmem_dptr(slot, id, &ptr); + if (ret != APR_SUCCESS) { + return ret; + } + *inuse=1; + memcpy(ptr, src, src_len); /* bounds check? */ + return APR_SUCCESS; +} + +static unsigned int slotmem_num_slots(ap_slotmem_instance_t *slot) +{ + return slot->num; +} + +static unsigned int slotmem_num_free_slots(ap_slotmem_instance_t *slot) +{ + unsigned int i, counter=0; + char *inuse = slot->inuse; + for (i = 0; i < slot->num; i++, inuse++) { + if (!*inuse) + counter++; + } + return counter; +} + +static apr_size_t slotmem_slot_size(ap_slotmem_instance_t *slot) +{ + return slot->size; +} + +/* + * XXXX: if !AP_SLOTMEM_IS_PREGRAB, then still worry about + * inuse for grab and return? + */ +static apr_status_t slotmem_grab(ap_slotmem_instance_t *slot, unsigned int *id) +{ + unsigned int i; + char *inuse; + + if (!slot) { + return APR_ENOSHMAVAIL; + } + + inuse = slot->inuse; + + for (i = 0; i < slot->num; i++, inuse++) { + if (!*inuse) { + break; + } + } + if (i >= slot->num) { + return APR_EINVAL; + } + *inuse = 1; + *id = i; + return APR_SUCCESS; +} + +static apr_status_t slotmem_fgrab(ap_slotmem_instance_t *slot, unsigned int id) +{ + char *inuse; + + if (!slot) { + return APR_ENOSHMAVAIL; + } + + if (id >= slot->num) { + return APR_EINVAL; + } + inuse = slot->inuse + id; + *inuse = 1; + return APR_SUCCESS; +} + +static apr_status_t slotmem_release(ap_slotmem_instance_t *slot, unsigned int id) +{ + char *inuse; + + if (!slot) { + return APR_ENOSHMAVAIL; + } + + inuse = slot->inuse; + + if (id >= slot->num) { + return APR_EINVAL; + } + if (!inuse[id] ) { + return APR_NOTFOUND; + } + inuse[id] = 0; + return APR_SUCCESS; +} + +static const ap_slotmem_provider_t storage = { + "plainmem", + &slotmem_do, + &slotmem_create, + &slotmem_attach, + &slotmem_dptr, + &slotmem_get, + &slotmem_put, + &slotmem_num_slots, + &slotmem_num_free_slots, + &slotmem_slot_size, + &slotmem_grab, + &slotmem_release, + &slotmem_fgrab +}; + +static int pre_config(apr_pool_t *p, apr_pool_t *plog, + apr_pool_t *ptemp) +{ + gpool = p; + return OK; +} + +static void ap_slotmem_plain_register_hook(apr_pool_t *p) +{ + /* XXX: static const char * const prePos[] = { "mod_slotmem.c", NULL }; */ + ap_register_provider(p, AP_SLOTMEM_PROVIDER_GROUP, "plain", + AP_SLOTMEM_PROVIDER_VERSION, &storage); + ap_hook_pre_config(pre_config, NULL, NULL, APR_HOOK_MIDDLE); +} + +AP_DECLARE_MODULE(slotmem_plain) = { + 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_slotmem_plain_register_hook /* register hooks */ +}; + |