You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by gs...@apache.org on 2010/06/08 20:23:35 UTC

svn commit: r952762 - in /apr/apr/branches/gstein-pocore: memory/unix/apr_pools.c tables/apr_hash.c

Author: gstein
Date: Tue Jun  8 18:23:34 2010
New Revision: 952762

URL: http://svn.apache.org/viewvc?rev=952762&view=rev
Log:
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

Modified:
    apr/apr/branches/gstein-pocore/memory/unix/apr_pools.c
    apr/apr/branches/gstein-pocore/tables/apr_hash.c

Modified: apr/apr/branches/gstein-pocore/memory/unix/apr_pools.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/gstein-pocore/memory/unix/apr_pools.c?rev=952762&r1=952761&r2=952762&view=diff
==============================================================================
--- apr/apr/branches/gstein-pocore/memory/unix/apr_pools.c (original)
+++ apr/apr/branches/gstein-pocore/memory/unix/apr_pools.c Tue Jun  8 18:23:34 2010
@@ -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(voi
 /* 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_
     }
     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_
     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
 
 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_poo
     /* 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_poo
     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_p
     /* 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_p
     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_creat
                                              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_creat
     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_creat
 
     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_creat
     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_creat
         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_creat
                                                   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_creat
 #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_creat
 
 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
     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_po
             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_po
     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_po
 
     list_remove(active);
     list_insert(active, node);
+#endif
 
     return strp;
 }
@@ -2036,6 +2175,10 @@ APR_DECLARE(apr_abortfunc_t) apr_pool_ab
 
 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_paren
     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(ap
     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(ap
     }
 
     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_po
 {
     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)

Modified: apr/apr/branches/gstein-pocore/tables/apr_hash.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/gstein-pocore/tables/apr_hash.c?rev=952762&r1=952761&r2=952762&view=diff
==============================================================================
--- apr/apr/branches/gstein-pocore/tables/apr_hash.c (original)
+++ apr/apr/branches/gstein-pocore/tables/apr_hash.c Tue Jun  8 18:23:34 2010
@@ -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(
     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_
                                                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_
 
 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
     }
     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
     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
                                 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_has
  * 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
     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(
         }
         *new_entry = NULL;
     }
+#endif
     return ht;
 }
 
@@ -326,12 +378,18 @@ APR_DECLARE(void *) apr_hash_get(apr_has
                                  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_
                                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_
         }
     }
     /* 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
                                                      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
         }
     }
     return res;
+#endif
 }
 
 APR_POOL_IMPLEMENT_ACCESSOR(hash)