diff options
author | Greg Stein <gstein@apache.org> | 2010-06-08 18:23:34 +0000 |
---|---|---|
committer | Greg Stein <gstein@apache.org> | 2010-06-08 18:23:34 +0000 |
commit | 3e523eba6b14c8179cfb79c434b048c33a81cda3 (patch) | |
tree | e4b47a0e6cb0cb121b9dadb44f8563f5af70a3c0 | |
parent | d8aaf8cb54f703278629661215324b3da1e62617 (diff) | |
download | apr-3e523eba6b14c8179cfb79c434b048c33a81cda3.tar.gz |
Stash my experimental rebuild of APR pools and hash tables atop PoCore.
See: http://groups.google.com/group/serf-dev/msg/59180e6cd4337dc4
* memory/unix/apr_pools.c: revamp to use PoCore pools. a few functions
have no correspondence, but it all works fine otherwise
* tables/apr_hash.c: revamp to use PoCore hash tables
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/branches/gstein-pocore@952762 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | memory/unix/apr_pools.c | 162 | ||||
-rw-r--r-- | tables/apr_hash.c | 115 |
2 files changed, 271 insertions, 6 deletions
diff --git a/memory/unix/apr_pools.c b/memory/unix/apr_pools.c index cb9a480c1..2e6284144 100644 --- a/memory/unix/apr_pools.c +++ b/memory/unix/apr_pools.c @@ -31,6 +31,12 @@ #include "apr_want.h" #include "apr_env.h" +/*#define USE_POCORE*/ +#ifdef USE_POCORE +#include "pc_memory.h" +#include "pc_misc.h" +#endif + #if APR_HAVE_STDLIB_H #include <stdlib.h> /* for malloc, free and abort */ #endif @@ -470,23 +476,31 @@ struct debug_node_t { * to see how it is used. */ struct apr_pool_t { +#ifdef USE_POCORE + pc_pool_t *pcpool; + pc_post_t *post; +#else apr_pool_t *parent; apr_pool_t *child; apr_pool_t *sibling; apr_pool_t **ref; +#endif cleanup_t *cleanups; cleanup_t *free_cleanups; +#ifndef USE_POCORE apr_allocator_t *allocator; +#endif struct process_chain *subprocesses; apr_abortfunc_t abort_fn; apr_hash_t *user_data; const char *tag; #if !APR_POOL_DEBUG +#ifndef USE_POCORE apr_memnode_t *active; apr_memnode_t *self; /* The node containing the pool itself */ char *self_first_avail; - +#endif #else /* APR_POOL_DEBUG */ apr_pool_t *joined; /* the caller has guaranteed that this pool * will survive as long as ->joined */ @@ -511,6 +525,13 @@ struct apr_pool_t { #define SIZEOF_POOL_T APR_ALIGN_DEFAULT(sizeof(apr_pool_t)) +#ifdef USE_POCORE +pc_pool_t *apr__get_pcpool(const apr_pool_t *pool) +{ + return pool->pcpool; +} +#endif + /* * Variables */ @@ -627,12 +648,30 @@ APR_DECLARE(void) apr_pool_terminate(void) /* Returns the amount of free space in the given node. */ #define node_free_space(node_) ((apr_size_t)(node_->endp - node_->first_avail)) +#if 0 +static void +log_action(const char *action, + void *pool, + void *parent, + apr_size_t amt) +{ + FILE *fp = fopen("/tmp/apr.log", "a"); + fprintf(fp, "%s %p %p %ld\n", action, pool, parent, (long)amt); + fclose(fp); +} +#else +#define log_action(a,b,c,d) ((void)0) +#endif + /* * Memory allocation */ APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t in_size) { +#ifdef USE_POCORE + return pc_alloc(pool->pcpool, in_size); +#else apr_memnode_t *active, *node; void *mem; apr_size_t size, free_index; @@ -646,6 +685,8 @@ APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t in_size) } active = pool->active; + log_action("alloc", pool, NULL, in_size); + /* If the active node has enough bytes left, use it. */ if (size <= node_free_space(active)) { mem = active->first_avail; @@ -693,6 +734,7 @@ APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t in_size) list_insert(active, node); return mem; +#endif } /* Provide an implementation of apr_pcalloc for backward compatibility @@ -722,18 +764,24 @@ APR_DECLARE(void *) apr_pcalloc(apr_pool_t *pool, apr_size_t size) APR_DECLARE(void) apr_pool_clear(apr_pool_t *pool) { +#ifndef USE_POCORE apr_memnode_t *active; +#endif + + log_action("clear", pool, NULL, 0); /* Run pre destroy cleanups */ run_cleanups(&pool->pre_cleanups); pool->pre_cleanups = NULL; pool->free_pre_cleanups = NULL; +#ifndef USE_POCORE /* Destroy the subpools. The subpools will detach themselves from * this pool thus this loop is safe and easy. */ while (pool->child) apr_pool_destroy(pool->child); +#endif /* Run cleanups */ run_cleanups(&pool->cleanups); @@ -747,6 +795,9 @@ APR_DECLARE(void) apr_pool_clear(apr_pool_t *pool) /* Clear the user data. */ pool->user_data = NULL; +#ifdef USE_POCORE + pc_post_recall(pool->post); +#else /* Find the node attached to the pool structure, reset it, make * it the active node and free the rest of the nodes. */ @@ -760,23 +811,30 @@ APR_DECLARE(void) apr_pool_clear(apr_pool_t *pool) allocator_free(pool->allocator, active->next); active->next = active; active->ref = &active->next; +#endif } APR_DECLARE(void) apr_pool_destroy(apr_pool_t *pool) { +#ifndef USE_POCORE apr_memnode_t *active; apr_allocator_t *allocator; +#endif + + log_action("destroy", pool, NULL, 0); /* Run pre destroy cleanups */ run_cleanups(&pool->pre_cleanups); pool->pre_cleanups = NULL; pool->free_pre_cleanups = NULL; +#ifndef USE_POCORE /* Destroy the subpools. The subpools will detach themselve from * this pool thus this loop is safe and easy. */ while (pool->child) apr_pool_destroy(pool->child); +#endif /* Run cleanups */ run_cleanups(&pool->cleanups); @@ -784,6 +842,9 @@ APR_DECLARE(void) apr_pool_destroy(apr_pool_t *pool) /* Free subprocesses */ free_proc_chain(pool->subprocesses); +#ifdef USE_POCORE + pc_pool_destroy(pool->pcpool); +#else /* Remove the pool from the parents child list */ if (pool->parent) { #if APR_HAS_THREADS @@ -831,6 +892,7 @@ APR_DECLARE(void) apr_pool_destroy(apr_pool_t *pool) if (apr_allocator_owner_get(allocator) == pool) { apr_allocator_destroy(allocator); } +#endif } APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool, @@ -839,7 +901,9 @@ APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool, apr_allocator_t *allocator) { apr_pool_t *pool; +#ifndef USE_POCORE apr_memnode_t *node; +#endif *newpool = NULL; @@ -853,6 +917,30 @@ APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool, if (!abort_fn && parent) abort_fn = parent->abort_fn; +#ifdef USE_POCORE + { + pc_pool_t *pcpool; + + if (parent == NULL) + { + pc_context_t *ctx = pc_context_create(); + + pcpool = pc_pool_root(ctx); + } + else + { + pcpool = pc_pool_create(parent->pcpool); + } + + pool = pc_alloc(pcpool, sizeof(*pool)); + pool->pcpool = pcpool; + + /* The APR pool is allocated within the PoCore pool. We don't want + to clear the pool and toss the APR pool. Set a post that we can + use for "clearing the [APR] pool". */ + pool->post = pc_post_create(pcpool); + } +#else if (allocator == NULL) allocator = parent->allocator; @@ -872,8 +960,9 @@ APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool, pool->allocator = allocator; pool->active = pool->self = node; - pool->abort_fn = abort_fn; pool->child = NULL; +#endif + pool->abort_fn = abort_fn; pool->cleanups = NULL; pool->free_cleanups = NULL; pool->pre_cleanups = NULL; @@ -886,6 +975,7 @@ APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool, pool->owner_proc = (apr_os_proc_t)getnlmhandle(); #endif /* defined(NETWARE) */ +#ifndef USE_POCORE if ((pool->parent = parent) != NULL) { #if APR_HAS_THREADS apr_thread_mutex_t *mutex; @@ -909,9 +999,12 @@ APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool, pool->sibling = NULL; pool->ref = NULL; } +#endif *newpool = pool; + log_action("create", pool, parent, 0); + return APR_SUCCESS; } @@ -928,14 +1021,21 @@ APR_DECLARE(apr_status_t) apr_pool_create_unmanaged_ex(apr_pool_t **newpool, apr_abortfunc_t abort_fn, apr_allocator_t *allocator) { +#ifndef USE_POCORE apr_pool_t *pool; apr_memnode_t *node; apr_allocator_t *pool_allocator; +#endif *newpool = NULL; if (!apr_pools_initialized) return APR_ENOPOOL; +#ifdef USE_POCORE + /* ### unmanaged is simply not hooking it into a ctx-rooted tree + ### is this sufficient? */ + apr_pool_create_ex(newpool, NULL, abort_fn, allocator); +#else if ((pool_allocator = allocator) == NULL) { if ((pool_allocator = malloc(SIZEOF_ALLOCATOR_T)) == NULL) { if (abort_fn) @@ -980,7 +1080,9 @@ APR_DECLARE(apr_status_t) apr_pool_create_unmanaged_ex(apr_pool_t **newpool, #endif /* defined(NETWARE) */ if (!allocator) pool_allocator->owner = pool; + *newpool = pool; +#endif return APR_SUCCESS; } @@ -1005,10 +1107,16 @@ APR_DECLARE(apr_status_t) apr_pool_create_unmanaged_ex(apr_pool_t **newpool, struct psprintf_data { apr_vformatter_buff_t vbuff; +#ifdef USE_POCORE + pc_pool_t *pcpool; + char *buf; + size_t buflen; +#else apr_memnode_t *node; apr_pool_t *pool; apr_byte_t got_a_new_node; apr_memnode_t *free; +#endif }; #define APR_PSPRINTF_MIN_STRINGSIZE 32 @@ -1016,6 +1124,22 @@ struct psprintf_data { static int psprintf_flush(apr_vformatter_buff_t *vbuff) { struct psprintf_data *ps = (struct psprintf_data *)vbuff; +#ifdef USE_POCORE + + size_t oldlen = ps->vbuff.curpos - ps->buf; + size_t newlen = ps->buflen * 2; + char *newbuf = pc_alloc(ps->pcpool, newlen); + + memcpy(newbuf, ps->buf, oldlen); + + ps->vbuff.curpos = newbuf + oldlen; + ps->vbuff.endpos = newbuf + newlen - 1; /* for NUL. */ + + ps->buf = newbuf; + ps->buflen = newlen; + + return 0; +#else apr_memnode_t *node, *active; apr_size_t cur_len, size; char *strp; @@ -1082,12 +1206,22 @@ static int psprintf_flush(apr_vformatter_buff_t *vbuff) ps->vbuff.endpos = node->endp - 1; /* Save a byte for NUL terminator */ return 0; +#endif } APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) { struct psprintf_data ps; char *strp; +#ifdef USE_POCORE + + ps.pcpool = pool->pcpool; + ps.buflen = 1000; + ps.buf = pc_alloc(ps.pcpool, ps.buflen); + + ps.vbuff.curpos = ps.buf; + ps.vbuff.endpos = ps.buf + ps.buflen - 1; /* for NUL */ +#else apr_size_t size; apr_memnode_t *active, *node; apr_size_t free_index; @@ -1113,6 +1247,7 @@ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) return NULL; } } +#endif if (apr_vformatter(psprintf_flush, &ps.vbuff, fmt, ap) == -1) { if (pool->abort_fn) @@ -1124,6 +1259,9 @@ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) strp = ps.vbuff.curpos; *strp++ = '\0'; +#ifdef USE_POCORE + strp = ps.buf; +#else size = strp - ps.node->first_avail; size = APR_ALIGN_DEFAULT(size); strp = ps.node->first_avail; @@ -1163,6 +1301,7 @@ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) list_remove(active); list_insert(active, node); +#endif return strp; } @@ -2036,6 +2175,10 @@ APR_DECLARE(apr_abortfunc_t) apr_pool_abort_get(apr_pool_t *pool) APR_DECLARE(apr_pool_t *) apr_pool_parent_get(apr_pool_t *pool) { +#ifdef USE_POCORE + /* ### we don't have this API in PoCore. should it be added? */ + return NULL; +#else #ifdef NETWARE /* On NetWare, don't return the global_pool, return the application pool as the top most pool */ @@ -2044,11 +2187,17 @@ APR_DECLARE(apr_pool_t *) apr_pool_parent_get(apr_pool_t *pool) else #endif return pool->parent; +#endif } APR_DECLARE(apr_allocator_t *) apr_pool_allocator_get(apr_pool_t *pool) { +#ifdef USE_POCORE + /* ### we don't have allocators in PoCore. should it be added? */ + return global_allocator; +#else return pool->allocator; +#endif } /* return TRUE if a is an ancestor of b @@ -2059,6 +2208,10 @@ APR_DECLARE(int) apr_pool_is_ancestor(apr_pool_t *a, apr_pool_t *b) if (a == NULL) return 1; +#ifdef USE_POCORE + /* ### we can't do this in pocore. */ + return 0; +#else #if APR_POOL_DEBUG /* Find the pool with the longest lifetime guaranteed by the * caller: */ @@ -2075,6 +2228,7 @@ APR_DECLARE(int) apr_pool_is_ancestor(apr_pool_t *a, apr_pool_t *b) } return 0; +#endif } APR_DECLARE(void) apr_pool_tag(apr_pool_t *pool, const char *tag) @@ -2331,8 +2485,12 @@ static void cleanup_pool_for_exec(apr_pool_t *p) { run_child_cleanups(&p->cleanups); +#ifdef USE_POCORE + /* ### we can't do this right now. */ +#else for (p = p->child; p; p = p->sibling) cleanup_pool_for_exec(p); +#endif } APR_DECLARE(void) apr_pool_cleanup_for_exec(void) diff --git a/tables/apr_hash.c b/tables/apr_hash.c index 4e3723e19..e52ba0d46 100644 --- a/tables/apr_hash.c +++ b/tables/apr_hash.c @@ -32,6 +32,13 @@ #include <stdio.h> #endif +/*#define USE_POCORE*/ +#ifdef USE_POCORE +#include "pc_types.h" +#include "pc_memory.h" +pc_pool_t *apr__get_pcpool(const apr_pool_t *pool); +#endif + /* * The internal form of a hash table. * @@ -41,6 +48,7 @@ * isn't too bad given that pools have a low allocation overhead. */ +#ifndef USE_POCORE typedef struct apr_hash_entry_t apr_hash_entry_t; struct apr_hash_entry_t { @@ -50,6 +58,7 @@ struct apr_hash_entry_t { apr_ssize_t klen; const void *val; }; +#endif /* * Data structure for iterating through a hash table. @@ -59,9 +68,13 @@ struct apr_hash_entry_t { * apr_hash_next(). */ struct apr_hash_index_t { +#ifdef USE_POCORE + pc_hiter_t *hi; +#else apr_hash_t *ht; apr_hash_entry_t *this, *next; unsigned int index; +#endif }; /* @@ -73,11 +86,15 @@ struct apr_hash_index_t { */ struct apr_hash_t { apr_pool_t *pool; - apr_hash_entry_t **array; apr_hash_index_t iterator; /* For apr_hash_first(NULL, ...) */ +#ifdef USE_POCORE + pc_hash_t *hash; +#else + apr_hash_entry_t **array; unsigned int count, max; apr_hashfunc_t hash_func; apr_hash_entry_t *free; /* List of recycled entries */ +#endif }; #define INITIAL_MAX 15 /* tunable == 2^n - 1 */ @@ -86,15 +103,22 @@ struct apr_hash_t { /* * Hash creation functions. */ - +#ifndef USE_POCORE static apr_hash_entry_t **alloc_array(apr_hash_t *ht, unsigned int max) { return apr_pcalloc(ht->pool, sizeof(*ht->array) * (max + 1)); } +#endif APR_DECLARE(apr_hash_t *) apr_hash_make(apr_pool_t *pool) { apr_hash_t *ht; +#ifdef USE_POCORE + pc_pool_t *pcpool = apr__get_pcpool(pool); + ht = pc_alloc(pcpool, sizeof(*ht)); + ht->pool = pool; + ht->hash = pc_hash_create(pcpool); +#else ht = apr_palloc(pool, sizeof(apr_hash_t)); ht->pool = pool; ht->free = NULL; @@ -102,6 +126,7 @@ APR_DECLARE(apr_hash_t *) apr_hash_make(apr_pool_t *pool) ht->max = INITIAL_MAX; ht->array = alloc_array(ht, ht->max); ht->hash_func = apr_hashfunc_default; +#endif return ht; } @@ -109,7 +134,9 @@ APR_DECLARE(apr_hash_t *) apr_hash_make_custom(apr_pool_t *pool, apr_hashfunc_t hash_func) { apr_hash_t *ht = apr_hash_make(pool); +#ifndef USE_POCORE ht->hash_func = hash_func; +#endif return ht; } @@ -120,6 +147,10 @@ APR_DECLARE(apr_hash_t *) apr_hash_make_custom(apr_pool_t *pool, APR_DECLARE(apr_hash_index_t *) apr_hash_next(apr_hash_index_t *hi) { +#ifdef USE_POCORE + hi->hi = pc_hiter_next(hi->hi); + return hi->hi ? hi : NULL; +#else hi->this = hi->next; while (!hi->this) { if (hi->index > hi->ht->max) @@ -129,6 +160,7 @@ APR_DECLARE(apr_hash_index_t *) apr_hash_next(apr_hash_index_t *hi) } hi->next = hi->this->next; return hi; +#endif } APR_DECLARE(apr_hash_index_t *) apr_hash_first(apr_pool_t *p, apr_hash_t *ht) @@ -139,11 +171,16 @@ APR_DECLARE(apr_hash_index_t *) apr_hash_first(apr_pool_t *p, apr_hash_t *ht) else hi = &ht->iterator; +#ifdef USE_POCORE + hi->hi = pc_hiter_begin(ht->hash, apr__get_pcpool(p)); + return hi->hi ? hi : NULL; +#else hi->ht = ht; hi->index = 0; hi->this = NULL; hi->next = NULL; return apr_hash_next(hi); +#endif } APR_DECLARE(void) apr_hash_this(apr_hash_index_t *hi, @@ -151,16 +188,22 @@ APR_DECLARE(void) apr_hash_this(apr_hash_index_t *hi, apr_ssize_t *klen, void **val) { +#ifdef USE_POCORE + if (key) *key = pc_hiter_key(hi->hi); + if (klen) *klen = pc_hiter_klen(hi->hi); + if (val) *val = pc_hiter_value(hi->hi); +#else if (key) *key = hi->this->key; if (klen) *klen = hi->this->klen; if (val) *val = (void *)hi->this->val; +#endif } /* * Expanding a hash table */ - +#ifndef USE_POCORE static void expand_array(apr_hash_t *ht) { apr_hash_index_t *hi; @@ -177,6 +220,7 @@ static void expand_array(apr_hash_t *ht) ht->array = new_array; ht->max = new_max; } +#endif APR_DECLARE_NONSTD(unsigned int) apr_hashfunc_default(const char *char_key, apr_ssize_t *klen) @@ -248,7 +292,7 @@ APR_DECLARE_NONSTD(unsigned int) apr_hashfunc_default(const char *char_key, * there isn't already one there; it returns an updatable pointer so * that hash entries can be removed. */ - +#ifndef USE_POCORE static apr_hash_entry_t **find_entry(apr_hash_t *ht, const void *key, apr_ssize_t klen, @@ -284,11 +328,18 @@ static apr_hash_entry_t **find_entry(apr_hash_t *ht, ht->count++; return hep; } +#endif APR_DECLARE(apr_hash_t *) apr_hash_copy(apr_pool_t *pool, const apr_hash_t *orig) { apr_hash_t *ht; +#ifdef USE_POCORE + pc_pool_t *pcpool = apr__get_pcpool(pool); + ht = pc_alloc(pcpool, sizeof(*ht)); + ht->pool = pool; + ht->hash = pc_hash_copy(orig->hash, pcpool); +#else apr_hash_entry_t *new_vals; unsigned int i, j; @@ -319,6 +370,7 @@ APR_DECLARE(apr_hash_t *) apr_hash_copy(apr_pool_t *pool, } *new_entry = NULL; } +#endif return ht; } @@ -326,12 +378,18 @@ APR_DECLARE(void *) apr_hash_get(apr_hash_t *ht, const void *key, apr_ssize_t klen) { +#ifdef USE_POCORE + if (klen == APR_HASH_KEY_STRING) + return pc_hash_gets(ht->hash, key); + return pc_hash_get(ht->hash, key, klen); +#else apr_hash_entry_t *he; he = *find_entry(ht, key, klen, NULL); if (he) return (void *)he->val; else return NULL; +#endif } APR_DECLARE(void) apr_hash_set(apr_hash_t *ht, @@ -339,6 +397,12 @@ APR_DECLARE(void) apr_hash_set(apr_hash_t *ht, apr_ssize_t klen, const void *val) { +#ifdef USE_POCORE + if (klen == APR_HASH_KEY_STRING) + pc_hash_sets(ht->hash, key, (void *)val); + else + pc_hash_set(ht->hash, key, klen, (void *)val); +#else apr_hash_entry_t **hep; hep = find_entry(ht, key, klen, val); if (*hep) { @@ -360,18 +424,27 @@ APR_DECLARE(void) apr_hash_set(apr_hash_t *ht, } } /* else key not present and val==NULL */ +#endif } APR_DECLARE(unsigned int) apr_hash_count(apr_hash_t *ht) { +#ifdef USE_POCORE + return pc_hash_count(ht->hash); +#else return ht->count; +#endif } APR_DECLARE(void) apr_hash_clear(apr_hash_t *ht) { +#ifdef USE_POCORE + pc_hash_clear(ht->hash); +#else apr_hash_index_t *hi; for (hi = apr_hash_first(NULL, ht); hi; hi = apr_hash_next(hi)) apr_hash_set(ht, hi->this->key, hi->this->klen, NULL); +#endif } APR_DECLARE(apr_hash_t*) apr_hash_overlay(apr_pool_t *p, @@ -392,6 +465,39 @@ APR_DECLARE(apr_hash_t *) apr_hash_merge(apr_pool_t *p, const void *data), const void *data) { +#ifdef USE_POCORE + pc_pool_t *pcpool = apr__get_pcpool(p); + apr_hash_t *result; + pc_hiter_t *hi; + + result = pc_alloc(pcpool, sizeof(*result)); + result->pool = p; + result->hash = pc_hash_copy(base->hash, pcpool); + + for (hi = pc_hiter_begin(overlay->hash, pcpool); + hi; + hi = pc_hiter_next(hi)) + { + const void *key = pc_hiter_key(hi); + size_t klen = pc_hiter_klen(hi); + void *new_value = pc_hiter_value(hi); + void *old_value = pc_hash_get(result->hash, key, klen); + + if (old_value == NULL || merger == NULL) + { + pc_hash_set(result->hash, key, klen, new_value); + } + else + { + pc_hash_set(result->hash, key, klen, + (*merger)(p, key, klen, + new_value, old_value, + data)); + } + } + + return result; +#else apr_hash_t *res; apr_hash_entry_t *new_vals = NULL; apr_hash_entry_t *iter; @@ -472,6 +578,7 @@ APR_DECLARE(apr_hash_t *) apr_hash_merge(apr_pool_t *p, } } return res; +#endif } APR_POOL_IMPLEMENT_ACCESSOR(hash) |