Author: jfrederic.clere(a)jboss.com
Date: 2008-05-14 09:34:30 -0400 (Wed, 14 May 2008)
New Revision: 1601
Modified:
trunk/mod_cluster/native/include/slotmem.h
trunk/mod_cluster/native/mod_slotmem/sharedmem_util.c
Log:
Use a more sophisticated version.
Modified: trunk/mod_cluster/native/include/slotmem.h
===================================================================
--- trunk/mod_cluster/native/include/slotmem.h 2008-05-14 09:07:33 UTC (rev 1600)
+++ trunk/mod_cluster/native/include/slotmem.h 2008-05-14 13:34:30 UTC (rev 1601)
@@ -1,17 +1,28 @@
-/* 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
+/*
+ * ALOHA - Apache Httpd Native Java Library
*
- *
http://www.apache.org/licenses/LICENSE-2.0
+ * Copyright(c) 2006 Red Hat Middleware, LLC,
+ * and individual contributors as indicated by the @authors tag.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
*
- * 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.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * @author Jean-Frederic Clere
+ * @version $Revision$
*/
#ifndef SLOTMEM_H
@@ -33,10 +44,6 @@
#include "apr_pools.h"
#include "apr_shm.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_log.h"
-
#define SLOTMEM_STORAGE "slotmem"
typedef struct ap_slotmem ap_slotmem_t;
@@ -45,10 +52,11 @@
* callback function used for slotmem.
* @param mem is the memory associated with a worker.
* @param data is what is passed to slotmem.
+ * @param int is id of the slotmem in the table.
* @param pool is pool used to create scoreboard
* @return APR_SUCCESS if all went well
*/
-typedef apr_status_t ap_slotmem_callback_fn_t(void* mem, void *data, apr_pool_t *pool);
+typedef apr_status_t ap_slotmem_callback_fn_t(void* mem, void **data, int ident,
apr_pool_t *pool);
struct slotmem_storage_method {
/**
@@ -59,7 +67,7 @@
* @param pool is pool used to create scoreboard
* @return APR_SUCCESS if all went well
*/
-AP_DECLARE(apr_status_t) (* slotmem)(ap_slotmem_t *s, ap_slotmem_callback_fn_t *func,
void *data, apr_pool_t *pool);
+APR_DECLARE(apr_status_t) (* ap_slotmem_do)(ap_slotmem_t *s, ap_slotmem_callback_fn_t
*func, void *data, apr_pool_t *pool);
/**
* create a new slotmem with each item size is item_size.
@@ -71,7 +79,7 @@
* @param pool is pool used to create scoreboard
* @return APR_SUCCESS if all went well
*/
-AP_DECLARE(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);
+APR_DECLARE(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);
/**
* attach to an existing slotmem.
@@ -83,17 +91,66 @@
* @param pool is pool to memory allocate.
* @return APR_SUCCESS if all went well
*/
-AP_DECLARE(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);
+APR_DECLARE(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);
/**
* get the memory associated with this worker slot.
* @param s ap_slotmem_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 (the slot must be an allocated slot).
+ */
+APR_DECLARE(apr_status_t) (* ap_slotmem_mem)(ap_slotmem_t *s, int item_id, void**mem);
+/**
+ * alloc a slot from the slotmem free idems.
+ * @param s ap_slotmem_t to use.
+ * @param item_id address to return the id of the slot allocates.
+ * @param mem address to store the pointer to the slot
* @return APR_SUCCESS if all went well
*/
-AP_DECLARE(apr_status_t) (* ap_slotmem_mem)(ap_slotmem_t *s, int item_id, void**mem);
+APR_DECLARE(apr_status_t) (* ap_slotmem_alloc)(ap_slotmem_t *s, int *item_id, void**mem);
+/**
+ * free a slot (return it to the free list).
+ * @param s ap_slotmem_t to use.
+ * @param item_id the id of the slot in the slotmem.
+ * @param mem pointer to the slot
+ * @return APR_SUCCESS if all went well
+ */
+APR_DECLARE(apr_status_t) (* ap_slotmem_free)(ap_slotmem_t *s, int item_id, void*mem);
+/**
+ * Lock the slotmem.
+ * @param s ap_slotmem_t to use.
+ * @return APR_SUCCESS if all went well
+ */
+APR_DECLARE(apr_status_t) (* ap_slotmem_lock)(ap_slotmem_t *s);
+/**
+ * Unlock the slotmem.
+ * @param s ap_slotmem_t to use.
+ * @return APR_SUCCESS if all went well
+ */
+APR_DECLARE(apr_status_t) (* ap_slotmem_unlock)(ap_slotmem_t *s);
+/**
+ * Return the used id in the slotmem table.
+ * @param s ap_slotmem_t to use.
+ * @param ids array of int where to store the free idents.
+ * @return number of slotmem in use.
+ */
+APR_DECLARE(int) (*ap_slotmem_get_used)(ap_slotmem_t *s, int *ids);
+/**
+ * Return the size of the slotmem table.
+ * @param s ap_slotmem_t to use.
+ * @return number of slotmem that cant be stored in the slotmem table.
+ */
+APR_DECLARE(int) (*ap_slotmem_get_max_size)(ap_slotmem_t *s);
};
typedef struct slotmem_storage_method slotmem_storage_method;
+/* Memory handler for a shared memory divided in slot.
+ * This one uses shared memory.
+ * @param pool is a global pool to allocate memory.
+ * @param type name of the module provider of charged memory.
+ * @return structure to the storage routines.
+ */
+const slotmem_storage_method *mem_getstorage(apr_pool_t *p, char *type);
+
#endif /*SLOTMEM_H*/
Modified: trunk/mod_cluster/native/mod_slotmem/sharedmem_util.c
===================================================================
--- trunk/mod_cluster/native/mod_slotmem/sharedmem_util.c 2008-05-14 09:07:33 UTC (rev
1600)
+++ trunk/mod_cluster/native/mod_slotmem/sharedmem_util.c 2008-05-14 13:34:30 UTC (rev
1601)
@@ -1,23 +1,33 @@
-/* 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
+/*
+ * mod_cluster.
*
- *
http://www.apache.org/licenses/LICENSE-2.0
+ * Copyright(c) 2008 Red Hat Middleware, LLC,
+ * and individual contributors as indicated by the @authors tag.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
*
- * 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.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * @author Jean-Frederic Clere
+ * @version $Revision$
*/
/* 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"
@@ -25,12 +35,7 @@
#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 {
@@ -41,10 +46,12 @@
struct ap_slotmem {
char *name;
apr_shm_t *shm;
+ int *ident; /* integer table to process a fast alloc/free */
void *base;
apr_size_t size;
int num;
apr_pool_t *globalpool;
+ apr_file_t *global_lock; /* file used for the locks */
struct ap_slotmem *next;
};
@@ -55,6 +62,7 @@
/*
* Persiste the slotmem in a file
* slotmem name and file name.
+ * for example use:
* anonymous : $server_root/logs/anonymous.slotmem
* :module.c : $server_root/logs/module.c.slotmem
* abs_name : $abs_name.slotmem
@@ -63,18 +71,7 @@
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");
- 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);
+ storename = apr_pstrcat(pool, slotmemname , ".slotmem", NULL);
return storename;
}
static void store_slotmem(ap_slotmem_t *slotmem)
@@ -94,15 +91,15 @@
if (rv != APR_SUCCESS) {
return;
}
- nbytes = slotmem->size * slotmem->num;
- apr_file_write(fp, slotmem->base, &nbytes);
+ nbytes = slotmem->size * slotmem->num + sizeof(int) * (slotmem->num + 1);
+ apr_file_write(fp, slotmem->ident, &nbytes);
apr_file_close(fp);
}
void restore_slotmem(void *ptr, const char *name, apr_size_t item_size, int item_num,
apr_pool_t *pool)
{
const char *storename;
apr_file_t *fp;
- apr_size_t nbytes = item_size * item_num;
+ apr_size_t nbytes = item_size * item_num + sizeof(int) * (item_num + 1);
apr_status_t rv;
storename = store_filename(pool, name);
@@ -135,28 +132,42 @@
while (next) {
store_slotmem(next);
rv = apr_shm_destroy(next->shm);
+ /* XXX: remove the lock file ? */
next = next->next;
}
- apr_pool_destroy(pool);
}
return APR_SUCCESS;
}
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;
+ int i, j, isfree, *ident;
void *ptr;
+ apr_status_t rv;
if (!mem) {
return APR_ENOSHMAVAIL;
}
+ /* performs the func only on allocated slots! */
ptr = mem->base;
- for (i = 0; i < mem->num; i++) {
+ for (i = 1; i < mem->num+1; i++) {
+ ident = mem->ident;
+ isfree = 0;
+ for (j=0; j<mem->num+1; j++) {
+ if (ident[j] == i) {
+ isfree = 1;
+ break;
+ }
+ }
+ if (!isfree) {
+ rv = func((void *)ptr, data, i, pool);
+ if (rv == APR_SUCCESS)
+ return(rv);
+ }
ptr = ptr + mem->size;
- func((void *)ptr, data, pool);
}
- return 0;
+ return APR_NOTFOUND;
}
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)
{
@@ -165,18 +176,16 @@
struct sharedslotdesc desc;
ap_slotmem_t *res;
ap_slotmem_t *next = globallistmem;
+ apr_status_t rv;
const char *fname;
- apr_status_t rv;
+ const char *filename;
+ apr_size_t nbytes = item_size * item_num + sizeof(int) * (item_num + 1) +
sizeof(struct sharedslotdesc);
+ int i, *ident;
if (globalpool == NULL)
return APR_ENOSHMAVAIL;
if (name) {
- if (name[0] == ':') {
- fname = name;
- }
- else {
- fname = ap_server_root_relative(pool, name);
- }
+ fname = name;
/* first try to attach to existing slotmem */
if (next) {
@@ -199,7 +208,7 @@
/* first try to attach to existing shared memory */
res = (ap_slotmem_t *) apr_pcalloc(globalpool, sizeof(ap_slotmem_t));
- if (name && name[0] != ':') {
+ if (name) {
rv = apr_shm_attach(&res->shm, fname, globalpool);
}
else {
@@ -207,14 +216,14 @@
}
if (rv == APR_SUCCESS) {
/* check size */
- if (apr_shm_size_get(res->shm) != item_size * item_num + sizeof(struct
sharedslotdesc)) {
+ if (apr_shm_size_get(res->shm) != nbytes) {
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) {
+ if (desc.item_size != item_size || desc.item_num != item_num) {
apr_shm_detach(res->shm);
res->shm = NULL;
return APR_EINVAL;
@@ -222,28 +231,44 @@
ptr = ptr + sizeof(desc);
}
else {
- if (name && name[0] != ':') {
+ if (name) {
apr_shm_remove(fname, globalpool);
- rv = apr_shm_create(&res->shm, item_size * item_num + sizeof(struct
sharedslotdesc), fname, globalpool);
+ rv = apr_shm_create(&res->shm, nbytes, fname, globalpool);
}
else {
- rv = apr_shm_create(&res->shm, item_size * item_num + sizeof(struct
sharedslotdesc), NULL, globalpool);
+ rv = apr_shm_create(&res->shm, nbytes, 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);
+ /* write the idents table */
+ ident = ptr;
+ for (i=0; i<item_num+1; i++) {
+ ident[i] = i + 1;
+ }
+ /* clean the slots table */
+ memset(ptr + sizeof(int) * (item_num + 1), 0, item_size * item_num);
+ /* try to restore the _whole_ stuff from a persisted location */
+ restore_slotmem(ptr, fname, item_size, item_num, pool);
}
+ /* create the lock */
+ filename = apr_pstrcat(pool, fname , ".lock", NULL);
+ rv = apr_file_open(&res->global_lock, filename, APR_WRITE|APR_CREATE,
APR_OS_DEFAULT, globalpool);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
/* For the chained slotmem stuff */
res->name = apr_pstrdup(globalpool, fname);
- res->base = ptr;
+ res->ident = ptr;
+ res->base = ptr + sizeof(int) * (item_num + 1);
res->size = item_size;
res->num = item_num;
res->globalpool = globalpool;
@@ -266,18 +291,14 @@
ap_slotmem_t *next = globallistmem;
struct sharedslotdesc desc;
const char *fname;
+ const char *filename;
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);
- }
+ fname = name;
}
else {
return APR_ENOSHMAVAIL;
@@ -305,6 +326,12 @@
if (rv != APR_SUCCESS) {
return rv;
}
+ /* get the corresponding lock */
+ filename = apr_pstrcat(pool, fname , ".lock", NULL);
+ rv = apr_file_open(&res->global_lock, filename, APR_WRITE|APR_CREATE,
APR_OS_DEFAULT, globalpool);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
/* Read the description of the slotmem */
ptr = apr_shm_baseaddr_get(res->shm);
@@ -313,7 +340,8 @@
/* For the chained slotmem stuff */
res->name = apr_pstrdup(globalpool, fname);
- res->base = ptr;
+ res->ident = ptr;
+ res->base = ptr + sizeof(int) * (desc.item_num + 1);
res->size = desc.item_size;
res->num = desc.item_num;
res->globalpool = globalpool;
@@ -334,6 +362,8 @@
{
void *ptr;
+ int i;
+ int *ident;
if (!score) {
return APR_ENOSHMAVAIL;
@@ -342,32 +372,110 @@
return APR_ENOSHMAVAIL;
}
- ptr = score->base + score->size * id;
+ /* Check that it is not a free slot */
+ ident = score->ident;
+ for (i=0; i<score->num+1; i++) {
+ if (ident[i] == id)
+ return APR_NOTFOUND;
+ }
+
+ ptr = score->base + score->size * (id - 1);
if (!ptr) {
return APR_ENOSHMAVAIL;
}
- ptr = score->base + score->size * id;
*mem = ptr;
return APR_SUCCESS;
}
+static apr_status_t ap_slotmem_lock(ap_slotmem_t *s)
+{
+ return(apr_file_lock(s->global_lock, APR_FLOCK_EXCLUSIVE));
+}
+static apr_status_t ap_slotmem_unlock(ap_slotmem_t *s)
+{
+ return(apr_file_unlock(s->global_lock));
+}
+static apr_status_t ap_slotmem_alloc(ap_slotmem_t *score, int *item_id, void**mem)
+{
+ int ff;
+ int *ident;
+ apr_status_t rv;
+ ap_slotmem_lock(score);
+ ident = score->ident;
+ ff = ident[0];
+ if (ff > score->num) {
+ rv = APR_ENOMEM;
+ } else {
+ ident[0] = ident[ff];
+ ident[ff] = 0;
+ *item_id = ff;
+ *mem = score->base + score->size * (ff - 1);
+ rv = APR_SUCCESS;
+ }
+
+ ap_slotmem_unlock(score);
+ return rv;
+}
+static apr_status_t ap_slotmem_free(ap_slotmem_t *score, int item_id, void*mem)
+{
+ int ff;
+ int *ident;
+ apr_status_t rv;
+ if (item_id > score->num || item_id <=0) {
+ return APR_EINVAL;
+ } else {
+ ap_slotmem_lock(score);
+ ident = score->ident;
+ if (ident[item_id]) {
+ ap_slotmem_unlock(score);
+ return APR_SUCCESS;
+ }
+ ff = ident[0];
+ ident[0] = item_id;
+ ident[item_id] = ff;
+ ap_slotmem_unlock(score);
+ return APR_SUCCESS;
+ }
+}
+static int ap_slotmem_get_used(ap_slotmem_t *score, int *ids)
+{
+ int i, ret = 0;
+ int *ident;
+ ident = score->ident;
+ for (i=0; i<score->num+1; i++) {
+ if (ident[i] == 0) {
+ *ids = i;
+ ids++;
+ ret++;
+ }
+ }
+ return ret;
+}
+static int ap_slotmem_get_max_size(ap_slotmem_t *score)
+{
+ return score->num;
+}
static const slotmem_storage_method storage = {
&ap_slotmem_do,
&ap_slotmem_create,
&ap_slotmem_attach,
- &ap_slotmem_mem
+ &ap_slotmem_mem,
+ &ap_slotmem_alloc,
+ &ap_slotmem_free,
+ &ap_slotmem_lock,
+ &ap_slotmem_unlock,
+ &ap_slotmem_get_used,
+ &ap_slotmem_get_max_size
};
-/* make the storage usuable from outside */
-const slotmem_storage_method *sharedmem_getstorage()
+/* make the storage usuable from outside
+ * and initialise the global pool */
+const slotmem_storage_method *mem_getstorage(apr_pool_t *p, char *type)
{
+ if (globalpool == NULL)
+ globalpool = p;
return(&storage);
}
-/* initialise the global pool */
-void sharedmem_initglobalpool(apr_pool_t *p)
-{
- globalpool = p;
-}
/* Add the pool_clean routine */
void sharedmem_initialize_cleanup(apr_pool_t *p)
{