Introduce dynamic memory pool for sessions

This pool has a fixed size and the aim is to avoid arbitrary limits
on entry's components, while maintaining an overall fixed entry size.

Accessors function for a storage unit are provided for future use.

Signed-off-by: Simo Sorce <simo@redhat.com>

git-svn-id: https://modmellon.googlecode.com/svn/trunk@231 a716ebb1-153a-0410-b759-cfb97c6a1b53
This commit is contained in:
olavmrk 2014-06-20 11:24:38 +00:00
parent 66f6d2cb08
commit 8dacb03887
5 changed files with 132 additions and 1 deletions

7
README
View File

@ -97,6 +97,13 @@ for mod_auth_mellon. The following is an example configuration:
# Default: MellonCacheSize 100
MellonCacheSize 100
# MellonCacheEntrySize sets the maximum size for a single session entry in
# bytes. When mod_auth_mellon reaches this limit, it cannot store any more
# data in the session and will return an error. The minimum entry size is
# 65536 bytes, values lower than that will be ignored and the minimum will
# be used.
# Default: MellonCacheEntrySize 196608
# MellonLockFile is the full path to a file used for synchronizing access
# to the session data. The path should only be used by one instance of
# apache at a time. The server must be restarted before any changes to this

View File

@ -78,6 +78,8 @@
#define AM_CACHE_MAX_LASSO_IDENTITY_SIZE 1024
#define AM_CACHE_MAX_LASSO_SESSION_SIZE 32768
#define AM_CACHE_MAX_LASSO_SAML_RESPONSE_SIZE 65536
#define AM_CACHE_DEFAULT_ENTRY_SIZE 196608
#define AM_CACHE_MIN_ENTRY_SIZE 65536
/* This is the length of the id we use (for session IDs and
@ -101,12 +103,15 @@ typedef struct am_mod_cfg_rec {
int post_count;
apr_size_t post_size;
int entry_size;
/* These variables can't be allowed to change after the session store
* has been initialized. Therefore we copy them before initializing
* the session store.
*/
int init_cache_size;
const char *init_lock_file;
apr_size_t init_entry_size;
apr_shm_t *cache;
apr_global_mutex_t *lock;
@ -240,6 +245,9 @@ typedef struct am_dir_cfg_rec {
LassoServer *server;
} am_dir_cfg_rec;
typedef struct am_cache_storage_t {
apr_uintptr_t ptr;
} am_cache_storage_t;
typedef struct am_cache_env_t {
char varname[AM_CACHE_VARSIZE];
@ -262,6 +270,10 @@ typedef struct am_cache_entry_t {
char lasso_saml_response[AM_CACHE_MAX_LASSO_SAML_RESPONSE_SIZE];
am_cache_env_t env[AM_CACHE_ENVSIZE];
apr_size_t pool_size;
apr_size_t pool_used;
char pool[];
} am_cache_entry_t;
typedef enum {
@ -322,6 +334,8 @@ void am_cookie_delete(request_rec *r);
am_cache_entry_t *am_cache_lock(server_rec *s,
am_cache_key_t type, const char *key);
const char *am_cache_entry_get_string(am_cache_entry_t *e,
am_cache_storage_t *slot);
am_cache_entry_t *am_cache_new(server_rec *s, const char *key);
void am_cache_unlock(server_rec *s, am_cache_entry_t *entry);

View File

@ -113,6 +113,96 @@ am_cache_entry_t *am_cache_lock(server_rec *s,
return NULL;
}
static inline void am_cache_storage_null(am_cache_storage_t *slot)
{
slot->ptr = 0;
}
static inline apr_size_t am_cache_entry_pool_left(am_cache_entry_t *e)
{
return e->pool_size - e->pool_used;
}
static inline apr_size_t am_cache_entry_pool_size(am_mod_cfg_rec *cfg)
{
return cfg->init_entry_size - sizeof(am_cache_entry_t);
}
/* This function sets a string into the specified storage on the entry.
*
* NOTE: The string pointer may be NULL, in that case storage is freed
* and set to NULL.
*
* Parametrs:
* am_cache_entry_t *entry Pointer to an entry
* am_cache_storage_t *slot Pointer to storage
* const char *string Pointer to a replacement string
*
* Returns:
* 0 on success, HTTP_INTERNAL_SERVER_ERROR on error.
*/
static int am_cache_entry_store_string(am_cache_entry_t *entry,
am_cache_storage_t *slot,
const char *string)
{
char *datastr = NULL;
apr_size_t datalen = 0;
apr_size_t str_len = 0;
if (string == NULL) return 0;
if (slot->ptr != 0) {
datastr = &entry->pool[slot->ptr];
datalen = strlen(datastr) + 1;
}
str_len = strlen(string) + 1;
if (str_len - datalen <= 0) {
memcpy(datastr, string, str_len);
return 0;
}
/* recover space if slot happens to point to the last allocated space */
if (slot->ptr + datalen == entry->pool_used) {
entry->pool_used -= datalen;
slot->ptr = 0;
}
if (am_cache_entry_pool_left(entry) < str_len) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
"apr_cache_entry_store_string() asked %zd available: %zd. "
"It may be a good idea to increase MellonCacheEntrySize.",
str_len, am_cache_entry_pool_left(entry));
return HTTP_INTERNAL_SERVER_ERROR;
}
slot->ptr = entry->pool_used;
datastr = &entry->pool[slot->ptr];
memcpy(datastr, string, str_len);
entry->pool_used += str_len;
return 0;
}
/* Returns a pointer to the string in the storage slot specified
*
*
* Parametrs:
* am_cache_entry_t *entry Pointer to an entry
* am_cache_storage_t *slot Pointer to storage slot
*
* Returns:
* A string or NULL if the slot is empty.
*/
const char *am_cache_entry_get_string(am_cache_entry_t *e,
am_cache_storage_t *slot)
{
char *ret = NULL;
if (slot->ptr != 0) {
ret = &e->pool[slot->ptr];
}
return ret;
}
/* This function locks the session table and creates a new session entry.
* It will first attempt to locate a free session. If it doesn't find a
@ -227,6 +317,10 @@ am_cache_entry_t *am_cache_new(server_rec *s, const char *key)
t->lasso_identity[0] = '\0';
t->lasso_session[0] = '\0';
t->pool_size = am_cache_entry_pool_size(mod_cfg);
t->pool[0] = '\0';
t->pool_used = 1;
return t;
}

View File

@ -862,6 +862,15 @@ const command_rec auth_mellon_commands[] = {
" restart the server before any changes to this directive will"
" take effect. The default value is 100."
),
AP_INIT_TAKE1(
"MellonCacheEntrySize",
am_set_module_config_int_slot,
(void *)APR_OFFSETOF(am_mod_cfg_rec, entry_size),
RSRC_CONF,
"The maximum size for a single session entry. You must"
" restart the server before any changes to this directive will"
" take effect. The default value is 192KiB."
),
AP_INIT_TAKE1(
"MellonLockFile",
am_set_module_config_file_slot,
@ -1571,8 +1580,11 @@ void *auth_mellon_server_config(apr_pool_t *p, server_rec *s)
mod->post_count = post_count;
mod->post_size = post_size;
mod->entry_size = AM_CACHE_DEFAULT_ENTRY_SIZE;
mod->init_cache_size = 0;
mod->init_lock_file = NULL;
mod->init_entry_size = 0;
mod->cache = NULL;
mod->lock = NULL;

View File

@ -88,9 +88,13 @@ static int am_global_init(apr_pool_t *conf, apr_pool_t *log,
*/
mod->init_cache_size = mod->cache_size;
mod->init_lock_file = apr_pstrdup(conf, mod->lock_file);
mod->init_entry_size = mod->entry_size;
if (mod->init_entry_size < AM_CACHE_MIN_ENTRY_SIZE) {
mod->init_entry_size = AM_CACHE_MIN_ENTRY_SIZE;
}
/* find out the memory size of the cache */
mem_size = sizeof(am_cache_entry_t) * mod->init_cache_size;
mem_size = mod->init_entry_size * mod->init_cache_size;
/* Create the shared memory, exit if it fails. */