blob: fb3d6e209897ac73965d4d1a327a061edcf5622c [file] [log] [blame]
/*
* Copyright 1999-2004 The Apache Software Foundation
*
* Licensed 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.
*/
/**
* Pool using APR.
*
* @author Costin Manolache
*/
#include "apr_pools.h"
#include "apr_strings.h"
#include "apr_network_io.h"
#include "apr_errno.h"
#include "apr_general.h"
#include "jk_global.h"
#include "jk_pool.h"
#include "jk_env.h"
/*
JK_APR_POOL_DEBUG will enable verbose messages on allocation.
What's important is to see 'reset' after each request.
*/
/** Nothing - apache will take care ??
*/
static void jk2_pool_apr_close(jk_env_t *env, jk_pool_t *p)
{
#ifdef JK_APR_POOL_DEBUG
fprintf(stderr, "apr_close %#lx\n", p);
#endif
}
/** Nothing - apache will take care.
XXX with jk pools we can implement 'recycling',
not sure what's the equivalent for apache
*/
static void jk2_pool_apr_reset(jk_env_t *env, jk_pool_t *p)
{
#ifdef JK_APR_POOL_DEBUG
fprintf(stderr, "apr_reset %#lx\n", p);
#endif
apr_pool_clear(p->_private);
}
static void *jk2_pool_apr_calloc(jk_env_t *env, jk_pool_t *p, size_t size)
{
#ifdef JK_APR_POOL_DEBUG
fprintf(stderr, "apr_calloc %#lx %d\n", p, size);
#endif
/* assert( p->_private != NULL ) */
return apr_pcalloc((apr_pool_t *) p->_private, (apr_size_t) size);
}
static void *jk2_pool_apr_alloc(jk_env_t *env, jk_pool_t *p, size_t size)
{
#ifdef JK_APR_POOL_DEBUG
fprintf(stderr, "apr_alloc %#lx %d\n", p, size);
#endif
return apr_palloc((apr_pool_t *) p->_private, (apr_size_t) size);
}
static void *jk2_pool_apr_realloc(jk_env_t *env, jk_pool_t *p,
size_t sz, const void *old, size_t old_sz)
{
void *rc;
#ifdef JK_APR_POOL_DEBUG
fprintf(stderr, "apr_realloc %#lx %d\n", p, sz);
#endif
if (!p || (!old && old_sz)) {
return NULL;
}
rc = jk2_pool_apr_alloc(env, p, sz);
if (rc) {
memcpy(rc, old, old_sz);
}
return rc;
}
static void *jk2_pool_apr_strdup(jk_env_t *env, jk_pool_t *p, const char *s)
{
#ifdef JK_APR_POOL_DEBUG
fprintf(stderr, "apr_strdup %#lx %d\n", p,
((s == NULL) ? -1 : (int)strlen(s)));
#endif
return apr_pstrdup((apr_pool_t *) p->_private, s);
}
static void jk2_pool_apr_initMethods(jk_env_t *env, jk_pool_t *_this);
static jk_pool_t *jk2_pool_apr_createChild(jk_env_t *env, jk_pool_t *_this,
int sizeHint)
{
apr_pool_t *parentAprPool = _this->_private;
apr_pool_t *childAprPool;
jk_pool_t *newPool;
apr_pool_create(&childAprPool, parentAprPool);
newPool = (jk_pool_t *)apr_palloc(parentAprPool, sizeof(jk_pool_t));
jk2_pool_apr_initMethods(env, newPool);
newPool->_private = childAprPool;
return newPool;
}
/** this is used to cache lengths in pstrcat */
#define MAX_SAVED_LENGTHS 6
static void *jk2_pool_apr_strcat(jk_env_t *env, jk_pool_t *p, ...)
{
char *cp, *argp, *res;
apr_size_t saved_lengths[MAX_SAVED_LENGTHS];
int nargs = 0;
/* Pass one --- find length of required string */
apr_size_t len = 0;
va_list adummy;
va_start(adummy, p);
while ((cp = va_arg(adummy, char *)) != NULL)
{
apr_size_t cplen = strlen(cp);
if (nargs < MAX_SAVED_LENGTHS) {
saved_lengths[nargs++] = cplen;
}
len += cplen;
}
va_end(adummy);
/* Allocate the required string */
res = (char *)apr_palloc(p->_private, len + 1);
cp = res;
/* Pass two --- copy the argument strings into the result space */
va_start(adummy, p);
nargs = 0;
while ((argp = va_arg(adummy, char *)) != NULL)
{
if (nargs < MAX_SAVED_LENGTHS) {
len = saved_lengths[nargs++];
}
else {
len = strlen(argp);
}
memcpy(cp, argp, len);
cp += len;
}
va_end(adummy);
/* Return the result string */
*cp = '\0';
return res;
}
int JK_METHOD jk2_pool_apr_create(jk_env_t *env, jk_pool_t **newPool,
jk_pool_t *parent, void *aprPoolV)
{
jk_pool_t *_this;
apr_pool_t *aprPool = (apr_pool_t *) aprPoolV;
_this = (jk_pool_t *)apr_palloc(aprPool, sizeof(jk_pool_t));
*newPool = _this;
_this->_private = aprPool;
jk2_pool_apr_initMethods(env, _this);
return JK_OK;
}
static void jk2_pool_apr_initMethods(jk_env_t *env, jk_pool_t *_this)
{
/* methods */
_this->create = jk2_pool_apr_createChild;
_this->close = jk2_pool_apr_close;
_this->reset = jk2_pool_apr_reset;
_this->alloc = jk2_pool_apr_alloc;
_this->calloc = jk2_pool_apr_calloc;
_this->pstrdup = jk2_pool_apr_strdup;
_this->realloc = jk2_pool_apr_realloc;
_this->pstrcat = jk2_pool_apr_strcat;
}
/* Not used yet */
int jk2_pool_apr_factory(jk_env_t *env, jk_pool_t *pool,
jk_bean_t *result, char *type, char *name)
{
jk_pool_t *_this = (jk_pool_t *)calloc(1, sizeof(jk_pool_t));
result->object = _this;
return JK_OK;
}