httpd-apreq-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j...@apache.org
Subject cvs commit: httpd-apreq-2/t performance.c Makefile.am cookie.c tables.c test_apreq.h testall.c
Date Sat, 03 May 2003 05:22:34 GMT
joes        2003/05/02 22:22:34

  Modified:    .        Makefile.am
               build    README
               env      mod_apreq.c
               src      apreq_tables.c apreq_tables.h
               t        Makefile.am cookie.c tables.c test_apreq.h
                        testall.c
  Added:       t        performance.c
  Log:
  Simplify table API a bit & add performance tests.
  
  Revision  Changes    Path
  1.6       +1 -1      httpd-apreq-2/Makefile.am
  
  Index: Makefile.am
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/Makefile.am,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Makefile.am	19 Apr 2003 09:42:08 -0000	1.5
  +++ Makefile.am	3 May 2003 05:22:33 -0000	1.6
  @@ -3,4 +3,4 @@
   EXTRA_DIST = INSTALL
   
   test: check
  -	t/testall
  \ No newline at end of file
  +	t/testall -v
  
  
  
  1.2       +5 -6      httpd-apreq-2/build/README
  
  Index: README
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/build/README,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- README	29 Apr 2003 16:49:14 -0000	1.1
  +++ README	3 May 2003 05:22:33 -0000	1.2
  @@ -4,7 +4,7 @@
   
   
   
  -UPDATING THE httpd-apreq HOME PAGE:
  +UPDATING THE httpd-apreq SITE:
   
   RedHat Linux:
     1) Download and install j2re and j2sdk rpms from Sun's
  @@ -16,8 +16,8 @@
   
           http://ant.apache.org/bindownload.cgi
   
  -    I just expanded the tar.gz file in /usr/java/ant, which
  -    is alongside the jre and jdk directory trees.
  +    (I just expanded the tar.gz file in /usr/java/ant, which
  +     is alongside the jre and jdk directory trees.)
   
     3) Prep the (bash) environment:
   
  @@ -28,9 +28,8 @@
     4) Check out httpd-site from cvs.apache.org and run
   
       $ cd httpd-site
  -    $ emacs xdocs/apreq/index.html
  +    $ emacs xdocs/apreq
       $ ant
  -    $ cvs commit -m "Added info on public cvs access, snapshots and list
  -    archives for apreq." xdocs/apreq/index.html docs/apreq/index.html
  +    $ cvs commit -m "..." xdocs/apreq/ docs/apreq/
   
     5) Wait 24 hours for the changes to appear on the website.
  
  
  
  1.11      +9 -0      httpd-apreq-2/env/mod_apreq.c
  
  Index: mod_apreq.c
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/env/mod_apreq.c,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- mod_apreq.c	25 Apr 2003 03:17:47 -0000	1.10
  +++ mod_apreq.c	3 May 2003 05:22:33 -0000	1.11
  @@ -135,6 +135,8 @@
       return c->jar;
   }
   
  +
  +
   static void *env_request(void *ctx, void *req)
   {
       dR;
  @@ -143,9 +145,16 @@
       if (req != NULL) {
           apreq_request_t *oldreq = c->req;
   
  +        /* XXX: this needs to be subrequest-friendly */
           if (oldreq == NULL) {
               dAPREQ_LOG;
               ap_filter_rec_t *f = ap_get_input_filter_handle(filter_name);
  +            if (r->main) {
  +                struct env_ctx *n = apreq_note(r->main);
  +                oldreq = n->req;
  +            }
  +
  +
               apreq_log(APREQ_DEBUG 0, r, "Adding APREQ filter to input chain");
               /* XXX: SOMEHOW INJECT APREQ INPUT FILTER */
               ap_add_input_filter_handle(f, NULL, r, r->connection);
  
  
  
  1.28      +100 -194  httpd-apreq-2/src/apreq_tables.c
  
  Index: apreq_tables.c
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq_tables.c,v
  retrieving revision 1.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- apreq_tables.c	29 Apr 2003 17:54:48 -0000	1.27
  +++ apreq_tables.c	3 May 2003 05:22:33 -0000	1.28
  @@ -69,13 +69,17 @@
   #include "apr_signal.h"
   
   /********************* table_entry structure ********************/
  +#define CS_TYPE   apr_uint32_t
  +#define CS_BYTES          4
  +#define OFFSET ((CS_BYTES-1) * 8)
  +
   
   /* private struct */
   
   typedef struct apreq_table_entry_t {
       const apreq_value_t *val;
       const char          *key;   /* = val->name : saves a ptr deref */
  -    apr_uint32_t         checksum;
  +    CS_TYPE              checksum;
       enum { RED, BLACK }  color;
       int                  tree[4];  /* LEFT RIGHT UP NEXT */
   } apreq_table_entry_t;
  @@ -99,25 +103,21 @@
   #define TABLE_HASH_SIZE 16
   #define TABLE_INDEX_MASK 0x0f
   #define TABLE_HASH(c)  (TABLE_INDEX_MASK & (unsigned char)(c))
  +
  +
   #define COMPUTE_KEY_CHECKSUM(k, checksum)    \
   {                                            \
  -    apr_uint32_t c = (apr_uint32_t)*(k);     \
  +    CS_TYPE c = (CS_TYPE)*(k);               \
  +    int j = 0;                               \
       (checksum) = c;                          \
  -    (checksum) <<= 8;                        \
  -    if (c) {                                 \
  -        c = (apr_uint32_t)*++(k);            \
  -        checksum |= c;                       \
  -    }                                        \
  -    (checksum) <<= 8;                        \
  -    if (c) {                                 \
  -        c = (apr_uint32_t)*++(k);            \
  -        checksum |= c;                       \
  -    }                                        \
  -    (checksum) <<= 8;                        \
  -    if (c) {                                 \
  -        c = (apr_uint32_t)*++(k);            \
  -        checksum |= c;                       \
  +    while (++j < CS_BYTES) {                 \
  +      (checksum) <<= 8;                      \
  +      if (c) {                               \
  +         c = (CS_TYPE)*++(k);                \
  +         checksum |= c;                      \
  +      }                                      \
       }                                        \
  +    if (c) ++(k);                            \
       checksum &= CASE_MASK;                   \
   }
   
  @@ -141,7 +141,6 @@
       apreq_value_merge_t *merge;
   
       int                  root[TABLE_HASH_SIZE];
  -    unsigned char        flags;
   };
   
   
  @@ -157,7 +156,7 @@
   
   /* NEVER KILL AN ENTRY THAT'S STILL WITHIN THE FOREST */
   #define IN_FOREST(t,idx) ( !DEAD(idx) && ( (idx)[o].tree[UP] >= 0 || \
  -                   (idx) == t->root[TABLE_HASH((idx)[o].checksum>>24)] ) )
  +                   (idx) == t->root[TABLE_HASH((idx)[o].checksum>>OFFSET)] ) )
   
   /* MUST ensure n's parent exists (>=0) before using LR(n) */
   #define LR(n) (  ( (n)[o].tree[UP][o].tree[LEFT] == (n) ) ? LEFT : RIGHT  )
  @@ -165,6 +164,7 @@
   #define PROMOTE(r,p)  do rotate(o,r,o[p].tree[UP],!LR(p)); \
                            while (o[p].tree[UP] >= 0)
   
  +
   /********************* (internal) tree operations ********************
    *
    * good general references for binary tree algorithms:
  @@ -183,11 +183,9 @@
    *   1   2                                 2  direction
    *
    */
  -
  -static APR_INLINE void rotate(apreq_table_entry_t *o, 
  -                              int *root,
  -                              const int pivot, 
  -                              const int direction)
  +APR_INLINE
  +static void rotate(apreq_table_entry_t *const o, int *root,
  +                   const int pivot, const int direction)
   {
       const int child   = pivot[o].tree[!direction];
       const int parent  = pivot[o].tree[UP];
  @@ -217,20 +215,19 @@
    * were it added to the tree.
    *
    */
  -static APR_INLINE int search(apreq_table_entry_t *o, 
  -                             int *elt,
  -                             const char *key) 
  -{
  -    int idx = *elt;
  -    apr_uint32_t checksum;
  -    if ( idx < 0)
  -        return 0;
  +APR_INLINE
  +static int search(const apreq_table_entry_t *const o,int *elt, 
  +                  const char *key)
  +{
  +    register int idx = *elt;
  +    register CS_TYPE csum;
   
  -    COMPUTE_KEY_CHECKSUM(key, checksum);
  +    COMPUTE_KEY_CHECKSUM(key, csum);
   
       while (1) {
  -        int direction = (checksum == idx[o].checksum) ? 
  -            strcasecmp(key,idx[o].key) : checksum - idx[o].checksum;
  +        const int direction = (csum > idx[o].checksum) ?  1 :
  +                              (csum < idx[o].checksum) ? -1 : 
  +                                  strcasecmp(key,idx[o].key);
   
           if (direction < 0 && idx[o].tree[LEFT] >= 0)
               idx = idx[o].tree[LEFT];
  @@ -248,16 +245,15 @@
   /* returns the index of the first similarly-named elt,
    * and -1 otherwise (the elt is new).
    */
  -static int insert(apreq_table_entry_t *o, int *root, int x,
  -                  apreq_table_entry_t *elt,
  -                  unsigned flags )
  +static int insert(apreq_table_entry_t *const o, int *root, int x,
  +                  apreq_table_entry_t *elt)
   {
  -    int idx = elt - o;
  -    int s;
  +    const int idx = elt - o;
  +    int s = 0;
   
   #define REBALANCE do {                                  \
       int parent = x[o].tree[UP];                         \
  -    x[o].color == RED;                                  \
  +    x[o].color = RED;                                   \
       if (parent >= 0 && parent[o].color == RED) {        \
           int parent_direction = LR(parent);              \
           int grandparent = parent[o].tree[UP];           \
  @@ -271,19 +267,23 @@
       } (*root)[o].color = BLACK; } while (0)
   
     
  -    if (flags & TF_BALANCE && *root != -1) {
  +    if (x >= 0) {
           /*
            * M.A. Weiss' single-pass insertion algorithm for red-black trees
            * corrects potential red-red violations prior to insertion:
            *      http://www.cs.uiowa.edu/~hzhang/c44/lec14.PDF
            */
   
  +        const CS_TYPE csum = elt->checksum;
  +        const char *const key = elt->key;
  +
           while (1) {
               int left = x[o].tree[LEFT];
               int right = x[o].tree[RIGHT];
   
  -            s = (elt->checksum == x[o].checksum) ? 
  -                strcasecmp(elt->key,x[o].key) : elt->checksum - x[o].checksum;
  +            s = (csum > x[o].checksum) ?  1 :
  +                (csum < x[o].checksum) ? -1 :
  +                    strcasecmp(key,x[o].key);
   
               if (s < 0 && left >= 0) {
                   if (left[o].color == RED && right >= 0 
  @@ -307,8 +307,6 @@
                   break;
           }
       }
  -    else
  -        s = search(o, &x, elt->val->name);
   
       if (s == 0) { /* found */
           int parent = x;
  @@ -341,17 +339,14 @@
       elt->tree[RIGHT] = -1;
       elt->tree[LEFT]  = -1;
   
  -    if (flags & TF_BALANCE) {
  -        elt->color = RED;
  -        x = idx;
  -        REBALANCE;
  -    }
  +    x = idx;
  +    REBALANCE;
  +
   #undef REBALANCE
       return -1;
   }
   
  -static void delete(apreq_table_entry_t *o, 
  -                   int *root,  const int idx, unsigned flags)
  +static void delete(apreq_table_entry_t *const o, int *root,  const int idx)
   {
       int x;
       int parent = idx[o].tree[UP];
  @@ -370,7 +365,7 @@
           else
               x = parent;
   
  -        if (flags & TF_BALANCE == 0 || idx[o].color == RED)
  +        if (idx[o].color == RED)
               return;
       }
       else {
  @@ -406,12 +401,10 @@
           else
               *root = y;
   
  -        if (flags & TF_BALANCE == 0 || y[o].color == RED) {
  -            y[o].color = idx[o].color;
  -            return;
  -        }
  -        else
  -            y[o].color = idx[o].color;
  +        if (y[o].color == RED)
  +            x = *root;
  +
  +        y[o].color = idx[o].color;
       }
   
   
  @@ -426,7 +419,7 @@
       while (x != *root && x[o].color == BLACK) {
           /* x has a parent & sibling */
           int parent = x[o].tree[UP];
  -        register const int direction = LR(x);
  +        const int direction = LR(x);
           int sibling = parent[o].tree[!direction];
   
           if (sibling[o].color == RED) {
  @@ -490,7 +483,7 @@
               a[o].tree[UP]         = -1;
           }
   
  -        if (insert(o,&a,a,b+o,0) < 0) /* b is a new element for a's tree */
  +        if (insert(o,&a,a,b+o) < 0) /* b is a new element for a's tree */
               rv = b;
   
           if (b[o].tree[UP] >= 0)
  @@ -567,7 +560,6 @@
   
       t->merge  = apreq_merge_values;
       t->copy   = apreq_copy_value;
  -    t->flags  = 0;
       t->ghosts = 0;
       return t;
   }
  @@ -585,7 +577,6 @@
       memcpy(new->root, t->root, TABLE_HASH_SIZE * sizeof(int));
       new->merge = t->merge;
       new->copy = t->copy;
  -    new->flags = t->flags;
       return new;
   }
   
  @@ -608,15 +599,13 @@
   }
   
   APREQ_DECLARE(apreq_table_t *)apreq_table_import(apr_pool_t *p, 
  -                                                 const apr_table_t *s, 
  -                                                 const unsigned f) 
  +                                                 const apr_table_t *s) 
   {
       apreq_table_t *t = apreq_table_make(p,APREQ_NELTS);
       const apr_array_header_t *a = apr_table_elts(s);
       const apr_table_entry_t *e = (const apr_table_entry_t *)a->elts;
       const apr_table_entry_t *end = e + a->nelts;
   
  -    t->flags = f;
   
       for ( ; e < end; ++e) {
           apreq_value_t *v = apreq_make_value(p, e->key, strlen(e->key), 
  @@ -676,29 +665,6 @@
   }
   
   
  -APREQ_DECLARE(void) apreq_table_balance(apreq_table_t *t, const int on)
  -{
  -    apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  -    if (on) {
  -        int idx;
  -        if (t->flags & TF_BALANCE)
  -            return;
  -
  -        memset(t->root,-1,TABLE_HASH_SIZE * sizeof(int));
  -        for (idx = 0; idx < t->a.nelts; ++idx)
  -            if (!DEAD(idx))
  -                insert(o, &t->root[TABLE_HASH(idx[o].checksum>>24)], 
  -                       t->root[TABLE_HASH(idx[o].checksum>>24)], idx+o, 
  -                       TF_BALANCE);
  -
  -        t->flags |= TF_BALANCE;
  -    }
  -    else {
  -        t->flags &= ~TF_BALANCE;
  -    }
  -}
  -
  -
   APREQ_DECLARE(apr_status_t) apreq_table_normalize(apreq_table_t *t)
   {
       apr_status_t status = APR_SUCCESS;
  @@ -818,29 +784,12 @@
                                                const char *key)
   {
       int idx = t->root[TABLE_HASH(*key)];
  -    apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  +    const apreq_table_entry_t *const o = (apreq_table_entry_t *)t->a.elts;
   
       if ( idx < 0 || search(o,&idx,key) )
   	return NULL;
   
  -    return v2c(idx[o].val);
  -}
  -
  -APREQ_DECLARE(const char *) apreq_table_cache(apreq_table_t *t,
  -                                              const char *key)
  -{
  -    int *root = &t->root[TABLE_HASH(*key)];
  -    int idx = *root;
  -    apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  -
  -    if ( idx < 0 || search(o,&idx,key) )
  -	return NULL;
  -
  -    if (idx != *root) {
  -        t->flags &= ~TF_BALANCE;
  -        PROMOTE(root,idx);
  -    }
  -    return v2c(idx[o].val);
  +    return idx[o].val->data;
   }
   
   
  @@ -860,48 +809,20 @@
   
   }
   
  -
  -APREQ_DECLARE(apr_status_t) apreq_table_values(const apreq_table_t *t,
  -                                               const char *key,
  -                                               apr_array_header_t *values)
  -{
  -    int idx;
  -    apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  -    if (t->a.nelts == t->ghosts)
  -        return APR_NOTFOUND;
  -
  -    if (key == NULL) {  /* fetch all values */
  -        for (idx = 0; idx < t->a.nelts; ++idx)
  -            if (IN_FOREST(t,idx))
  -                *(const apreq_value_t **)apr_array_push(values) = idx[o].val;
  -    }
  -    else {
  -        idx = t->root[TABLE_HASH(*key)];
  -        if ( idx>=0 && search(o,&idx,key) == 0 )
  -           for ( ; idx>=0; idx = idx[o].tree[NEXT] )
  -                *(const apreq_value_t **)apr_array_push(values) = idx[o].val;
  -        else
  -            return APR_NOTFOUND;
  -    }
  -
  -    return APR_SUCCESS;
  -}
  -
  -
   APREQ_DECLARE(void) apreq_table_set(apreq_table_t *t, 
                                       const apreq_value_t *val)
   {
       const char *key = val->name;
       int idx;
       apreq_table_entry_t *e = table_push(t);
  -    apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  +    apreq_table_entry_t *const o = (apreq_table_entry_t *)t->a.elts;
   
       e->key = key;
       e->val = val;
       e->tree[NEXT] = -1;
       COMPUTE_KEY_CHECKSUM(e->key,e->checksum);
       idx = insert(o,&t->root[TABLE_HASH(*key)], 
  -                 t->root[TABLE_HASH(*key)] ,e,t->flags);
  +                 t->root[TABLE_HASH(*key)] ,e);
   
       if (idx >= 0) {
           int n;
  @@ -922,11 +843,11 @@
   APREQ_DECLARE(void) apreq_table_unset(apreq_table_t *t, const char *key)
   {
       int idx = t->root[TABLE_HASH(*key)];
  -    apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  +    apreq_table_entry_t *const o = (apreq_table_entry_t *)t->a.elts;
   
       if (idx >= 0 && search(o,&idx,key) == 0) {
           int n;
  -        delete(o,&t->root[TABLE_HASH(*key)],idx, t->flags);
  +        delete(o,&t->root[TABLE_HASH(*key)],idx);
           for ( n=idx; n>=0; n=n[o].tree[NEXT] )
               KILL(t,n);
       }
  @@ -939,13 +860,13 @@
       const char *key = val->name;
       int idx = t->root[TABLE_HASH(*key)];
       apreq_table_entry_t *e = table_push(t);
  -    apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  +    apreq_table_entry_t *const o = (apreq_table_entry_t *)t->a.elts;
   
       e->key = key;
       e->val = val;
       e->tree[NEXT] = -1;
       COMPUTE_KEY_CHECKSUM(key,e->checksum);
  -    idx = insert(o,&t->root[TABLE_HASH(*key)],idx,e,t->flags);
  +    idx = insert(o,&t->root[TABLE_HASH(*key)],idx,e);
   
       if (idx >= 0) {
           int n;
  @@ -988,32 +909,16 @@
   APREQ_DECLARE(apr_status_t) apreq_table_add(apreq_table_t *t, 
                                               const apreq_value_t *val)
   {
  -    if (val == NULL || val->name == NULL)
  -        return APR_EGENERAL;
  -
  -    switch (val->status) {
  -    case APR_SUCCESS:
  -    case APR_EINPROGRESS:
  -    case APR_INCOMPLETE:
  -    {
  -        const char *key = val->name;
  -        apreq_table_entry_t *elt = table_push(t);
  -        int *root = &t->root[TABLE_HASH(*key)];
  -        apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  -
  -        elt->key = key;
  -        elt->val = val;
  -        elt->tree[NEXT] = -1;
  -        COMPUTE_KEY_CHECKSUM(elt->key,elt->checksum);
  -        insert(o, root, *root, elt, t->flags);
  -        return APR_SUCCESS;
  -    }
  -
  -    default:
  -        return val->status;
  -    }
  +    const char *key = val->name;
  +    apreq_table_entry_t *elt = table_push(t);
  +    int *root = &t->root[TABLE_HASH(*key)];
  +    apreq_table_entry_t *const o = (apreq_table_entry_t *)t->a.elts;
   
  -    /* NOT REACHED */
  +    elt->key = key;
  +    elt->val = val;
  +    elt->tree[NEXT] = -1;
  +    COMPUTE_KEY_CHECKSUM(elt->key,elt->checksum);
  +    insert(o, root, *root, elt);
       return APR_SUCCESS;
   }
   
  @@ -1029,9 +934,10 @@
       int idx;
       apreq_table_entry_t *o;
       if (t->ghosts == n) {
  -        t->a.nelts == 0;
  +        t->a.nelts = 0;
           t->ghosts = s->ghosts;
           apr_array_cat(&t->a,&s->a);
  +        memcpy(t->root, s->root, TABLE_HASH_SIZE * sizeof(int));
           return;
       }
   
  @@ -1039,35 +945,36 @@
       o = (apreq_table_entry_t *)t->a.elts;
       t->ghosts += s->ghosts;
   
  -    if (t->flags & TF_BALANCE) {
  -        for (idx = n; idx < t->a.nelts; ++idx) {
  -            const unsigned char hash = TABLE_HASH(idx[o].checksum>>24);
  -
  -            if (DEAD(idx))
  -                continue;
  -
  -            if (idx[o].tree[NEXT] >= 0)
  -                idx[o].tree[NEXT] += n;
  -
  -            if (t->root[hash] < 0) {
  -                if (idx[o].tree[LEFT] >= 0)
  -                    idx[o].tree[LEFT] += n;
  -                if (idx[o].tree[RIGHT] >= 0)
  -                    idx[o].tree[RIGHT] += n;
  -                if (idx[o].tree[UP] >= 0)
  -                    idx[o].tree[UP] += n;
  +    for (idx = n; idx < t->a.nelts; ++idx) {
  +        const unsigned char hash = TABLE_HASH(idx[o].checksum>>OFFSET);
   
  -                t->root[hash] = idx;
  -            }
  -            else if ( idx[o].tree[UP] >= 0 || s->root[hash] == idx-n ) 
  -                insert(o, &t->root[hash], t->root[hash], idx+o, TF_BALANCE);
  +        if (DEAD(idx))
  +            continue;
  +
  +        if (idx[o].tree[NEXT] >= 0)
  +            idx[o].tree[NEXT] += n;
  +
  +        if (t->root[hash] < 0) {
  +            if (idx[o].tree[LEFT] >= 0)
  +                idx[o].tree[LEFT] += n;
  +            if (idx[o].tree[RIGHT] >= 0)
  +                idx[o].tree[RIGHT] += n;
  +            if (idx[o].tree[UP] >= 0)
  +                idx[o].tree[UP] += n;
  +
  +            t->root[hash] = idx;
           }
  +        else if ( idx[o].tree[UP] >= 0 || s->root[hash] == idx-n ) 
  +            insert(o, &t->root[hash], t->root[hash], idx+o);
       }
  +}
  +/*
       else {
           for (idx = 0; idx < TABLE_HASH_SIZE; ++idx)
               t->root[idx] = combine(o,t->root[idx],s->root[idx],n);
       }
   }
  +*/
   
   APREQ_DECLARE(apreq_table_t *) apreq_table_overlay(apr_pool_t *p,
                                                const apreq_table_t *overlay,
  @@ -1079,7 +986,6 @@
       t->a.elt_size = sizeof(apreq_table_entry_t);
       t->copy = overlay->copy;
       t->merge = overlay->merge;
  -    t->flags = overlay->flags;
       t->ghosts = overlay->ghosts;
   
       memcpy(t->root, overlay->root, TABLE_HASH_SIZE * sizeof(int));
  @@ -1247,7 +1153,7 @@
                                      va_list vp)
   {
       char *argp;
  -    apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  +    const apreq_table_entry_t *const o = (apreq_table_entry_t *)t->a.elts;
       int vdorv = 1;
   
       argp = va_arg(vp, char *);
  @@ -1255,9 +1161,9 @@
           int rv = 1, idx;
           if (argp) {     /* Scan for entries that match the next key */
               idx = t->root[TABLE_HASH(*argp)];
  -            if ( search(o,&idx,argp) == 0 )
  +            if ( idx >= 0 && search(o,&idx,argp) == 0 )
                   while (idx >= 0) {
  -                    rv = (*comp) (rec, idx[o].val->name, v2c(idx[o].val));
  +                    rv = (*comp) (rec, idx[o].key, idx[o].val->data);
                       idx = idx[o].tree[NEXT];
                   }
           }
  @@ -1265,7 +1171,7 @@
               for (idx = 0; rv && (idx < t->a.nelts); ++idx)
                   /* if (idx[o].key) */
                   if (! DEAD(idx) )
  -                    rv = (*comp) (rec, idx[o].val->name, v2c(idx[o].val));
  +                    rv = (*comp) (rec, idx[o].key, idx[o].val->data);
           }
           if (rv == 0) {
               vdorv = 0;
  
  
  
  1.16      +2 -45     httpd-apreq-2/src/apreq_tables.h
  
  Index: apreq_tables.h
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq_tables.h,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- apreq_tables.h	29 Apr 2003 03:35:55 -0000	1.15
  +++ apreq_tables.h	3 May 2003 05:22:33 -0000	1.16
  @@ -124,11 +124,9 @@
    * Create an APREQ Table from an APR Table.
    * @param p The pool to allocate the APREQ table from
    * @param t The APR table to copy
  - * @param f Flags for the APREQ table to use during construction.
    */
   APREQ_DECLARE(apreq_table_t *)apreq_table_import(apr_pool_t *p, 
  -                                                 const apr_table_t *t, 
  -                                                 const unsigned f);
  +                                                 const apr_table_t *t);
   
   /**
    * Delete all of the elements from a table
  @@ -145,6 +143,7 @@
   APREQ_DECLARE(int) apreq_table_nelts(const apreq_table_t *t);
   #define apreq_table_is_empty(t) ( apreq_table_nelts(t) == 0 )
   
  +
   /**
    * Get/set method for the table's value copier.
    * @param t Table.
  @@ -168,21 +167,6 @@
                                              apreq_value_merge_t *m);
   
   /**
  - * Change the behavior of the table's internal search trees.
  - * @param t  Table.
  - * @param on Activate/deactivate additional balancing algorithms.
  - * @remark   By default, APREQ Tables use binary search trees to 
  - *           improve lookup performance.  This function can instruct
  - *           the table to maintain balance within those trees.  
  - *           In typical ( < 100 table entries ) situations, the 
  - *           additional overhead needed for maintaining tree-balance 
  - *           will cause performance to worsen, not improve.  
  - *
  - *           Handle with care.
  - */
  -APREQ_DECLARE(void) apreq_table_balance(apreq_table_t *t, const int on);
  -
  -/**
    * Attempt to merge multivalued entries together, eliminating
    * redunandant entries with t->merge.  See apreq_table_merger 
    * for additional details.
  @@ -224,21 +208,6 @@
                                              const char *key);
   
   /**
  - * Get the value associated with a given key from the table,
  - * and cache the entry at the root of the tree it was found in.
  - * @param t The table to search for the key
  - * @param key The key to search for
  - * @return The data associated with the key, guaranteed to
  - * point at the "data" attribute of an apreq_value_t struct.
  - *
  - * @remark Caching is incompatible with tree-balance, so this 
  - * function may deactivate the tree-balancing algorithm if
  - * necessary.
  - */
  -APREQ_DECLARE(const char *) apreq_table_cache(apreq_table_t *t,
  -                                              const char *key);
  -
  -/**
    * Return the keys (i.e. value names) in an (char *) array,
    * preserving their original order.
    * @param t Table.
  @@ -248,18 +217,6 @@
   APREQ_DECLARE(apr_status_t) apreq_table_keys(const apreq_table_t *t,
                                                apr_array_header_t *keys);
   
  -/**
  - * Return the (unique) values in an (apreq_value_t *) array,
  - * preserving their original order.
  - * @param t Table.
  - * @param values array used to sore the result..
  - * @remark With key == NULL, all table values are added.  However,
  - * only the first value of a multivalued entry is used.
  - */
  -
  -APREQ_DECLARE(apr_status_t) apreq_table_values(const apreq_table_t *t,
  -                                               const char *key,
  -                                               apr_array_header_t *values);
   /**
    * Add an apreq_value_t to the table. If another value already exists
    * with the same name, this will replace the old value.
  
  
  
  1.7       +1 -1      httpd-apreq-2/t/Makefile.am
  
  Index: Makefile.am
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/t/Makefile.am,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- Makefile.am	24 Apr 2003 20:17:17 -0000	1.6
  +++ Makefile.am	3 May 2003 05:22:33 -0000	1.7
  @@ -2,7 +2,7 @@
   LIBS = -L../src
   
   noinst_LIBRARIES = libapreq_tests.a
  -libapreq_tests_a_SOURCES = CuTest.c env.c tables.c cookie.c params.c parsers.c
  +libapreq_tests_a_SOURCES = CuTest.c env.c tables.c cookie.c params.c parsers.c performance.c
   libapreq_tests_a_LIBADD = ../src/libapreq.la
   
   check_PROGRAMS = testall
  
  
  
  1.3       +2 -3      httpd-apreq-2/t/cookie.c
  
  Index: cookie.c
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/t/cookie.c,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- cookie.c	21 Apr 2003 19:40:11 -0000	1.2
  +++ cookie.c	3 May 2003 05:22:33 -0000	1.3
  @@ -95,7 +95,6 @@
   {
       apreq_cookie_t *c;
       apreq_cookie_version_t version = NETSCAPE;
  -    char *expires = apreq_expires(p,"+1y", NSCOOKIE);
   
       c = apreq_cookie(j,"foo");
       CuAssertStrEquals(tc,"bar",apreq_cookie_value(c));
  @@ -109,11 +108,10 @@
       c->path = apr_pstrdup(p, "/quux");
       CuAssertStrEquals(tc, "foo=bar; path=/quux; domain=example.com",
                         apreq_cookie_as_string(p,c));
  -
       apreq_cookie_expires(p, c, "+1y");
       CuAssertStrEquals(tc,apr_pstrcat(p,
                            "foo=bar; path=/quux; domain=example.com; expires=", 
  -                         expires, NULL), apreq_cookie_as_string(p,c));
  +                         apreq_expires(p,"+1y",NSCOOKIE), NULL), apreq_cookie_as_string(p,c));
   }
   
   
  @@ -153,6 +151,7 @@
       SUITE_ADD_TEST(suite, jar_table_get);
       SUITE_ADD_TEST(suite, netscape_cookie);
       SUITE_ADD_TEST(suite, rfc_cookie);
  +
       return suite;
   }
   
  
  
  
  1.9       +23 -27    httpd-apreq-2/t/tables.c
  
  Index: tables.c
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/t/tables.c,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- tables.c	25 Apr 2003 18:11:15 -0000	1.8
  +++ tables.c	3 May 2003 05:22:33 -0000	1.9
  @@ -75,7 +75,6 @@
   {
       t1 = apreq_make_table(p, 5);
       CuAssertPtrNotNull(tc, t1);
  -    apreq_table_balance(t1,1);
   }
   
   static void table_get(CuTest *tc)
  @@ -310,6 +309,7 @@
   {
       const char *k;
       apr_array_header_t *a = apr_array_make(p,1, sizeof k);
  +
       apr_status_t s = apreq_table_keys(t1,a);
       CuAssertIntEquals(tc, APR_SUCCESS, s);
       CuAssertIntEquals(tc, 7, a->nelts);
  @@ -329,39 +329,35 @@
       CuAssertStrEquals(tc, "f", k);
   }
   
  +static int push_value(void *d, const char *key, const char *val)
  +{
  +    apr_array_header_t *a = d;
  +    *(const char **)apr_array_push(a) = val;
  +    return 1;
  +}
  +
   static void table_values(CuTest *tc)
   {
  -    const apreq_value_t *v;
  +    const char *v;
       apr_array_header_t *a = apr_array_make(p,1,sizeof v);
  -    apr_status_t s = apreq_table_values(t1,"a",a);
  -    CuAssertIntEquals(tc, APR_SUCCESS, s);
  +    apreq_table_do(push_value, a, t1, "a", NULL);
  +
       CuAssertIntEquals(tc, 2, a->nelts);
  -    v = ((const apreq_value_t **)a->elts)[0];
  -    CuAssertStrEquals(tc, "a", v->name);
  -    CuAssertStrEquals(tc, "0", v->data);
  -    v = ((const apreq_value_t **)a->elts)[1];
  -    CuAssertStrEquals(tc, "a", v->name);
  -    CuAssertStrEquals(tc, "1", v->data);
  +    v = ((const char **)a->elts)[0];
  +    CuAssertStrEquals(tc, "0", v);
  +    v = ((const char **)a->elts)[1];
  +    CuAssertStrEquals(tc, "1", v);
   
       a->nelts = 0;
  -    s = apreq_table_values(t1,"b",a);
  -    CuAssertIntEquals(tc, APR_SUCCESS, s);
  -    CuAssertIntEquals(tc, 3, a->nelts);
  -    v = ((const apreq_value_t **)a->elts)[0];
  -    CuAssertStrEquals(tc, "b", v->name);
  -    CuAssertStrEquals(tc, "2", v->data);
  -    v = ((const apreq_value_t **)a->elts)[1];
  -    CuAssertStrEquals(tc, "b", v->name);
  -    CuAssertStrEquals(tc, "2.0", v->data);
  -    v = ((const apreq_value_t **)a->elts)[2];
  -    CuAssertStrEquals(tc, "b", v->name);
  -    CuAssertStrEquals(tc, "2.", v->data);
  +    apreq_table_do(push_value, a, t1, "b", NULL);
   
  -    a->nelts = 0;
  -    s = apreq_table_values(t1,NULL,a);
  -    CuAssertIntEquals(tc, APR_SUCCESS, s);
  -    CuAssertIntEquals(tc, 7, a->nelts);
  -    
  +    CuAssertIntEquals(tc, 3, a->nelts);
  +    v = ((const char **)a->elts)[0];
  +    CuAssertStrEquals(tc, "2", v);
  +    v = ((const char **)a->elts)[1];
  +    CuAssertStrEquals(tc, "2.0", v);
  +    v = ((const char **)a->elts)[2];
  +    CuAssertStrEquals(tc, "2.", v);
   }
   
   
  
  
  
  1.5       +1 -1      httpd-apreq-2/t/test_apreq.h
  
  Index: test_apreq.h
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/t/test_apreq.h,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- test_apreq.h	24 Apr 2003 20:17:17 -0000	1.4
  +++ test_apreq.h	3 May 2003 05:22:33 -0000	1.5
  @@ -71,7 +71,7 @@
   CuSuite *testenv(void);
   CuSuite *testparam(void);
   CuSuite *testparser(void);
  -
  +CuSuite *testperformance(void);
   /* Assert that RV is an APR_SUCCESS value; else fail giving strerror
    * for RV and CONTEXT message. */
   void apr_assert_success(CuTest* tc, const char *context, apr_status_t rv);
  
  
  
  1.7       +1 -0      httpd-apreq-2/t/testall.c
  
  Index: testall.c
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/t/testall.c,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- testall.c	24 Apr 2003 20:17:17 -0000	1.6
  +++ testall.c	3 May 2003 05:22:33 -0000	1.7
  @@ -82,6 +82,7 @@
       {"cookies", testcookie},
       {"params", testparam},
       {"parsers", testparser},
  +    {"performance", testperformance},
       {"LastTest", NULL}
   };
   
  
  
  
  1.1                  httpd-apreq-2/t/performance.c
  
  Index: performance.c
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  #include "apr_time.h"
  #include "apr_strings.h"
  #include "apreq_env.h"
  #include "test_apreq.h"
  #include "apreq.h"
  #include "apreq_tables.h"
  #include "apr_hash.h"
  #if APR_HAVE_STDIO_H
  #include <stdio.h>
  #endif
  #if APR_HAVE_STDLIB_H
  #include <stdlib.h>
  #endif
  #if APR_HAVE_STRING_H
  #include <string.h>
  #endif
  
  static apreq_table_t *t = NULL;
  static apreq_table_t *s = NULL;
  static apreq_table_t *h = NULL;
  
  #define LOOP 10000
  #define FAIL(MSG) \
    CuFail(tc, apr_psprintf(p, MSG ": APR = %.3f vs APREQ = %.3f (microseconds)", \
                           (double)apr_delta / LOOP, (double)apreq_delta / LOOP))
  #define TEST_DELTAS(winner,loser,MSG)     if (winner##_delta > loser##_delta) FAIL(MSG)
  
  #define RUN_GET(k,v) do {apr_time_t apr_delta,apreq_delta;const char *val; \
     int i; apreq_delta = apr_time_now(); for(i=0;i<LOOP;++i) val = \
     apreq_table_get(t,k); apreq_delta = apr_time_now() - apreq_delta; \
     if (v) { CuAssertPtrNotNull(tc,val);CuAssertStrEquals(tc,v,val);} \
     else CuAssertPtrEquals(tc,NULL,val); \
     apr_delta = apr_time_now(); for(i=0;i<LOOP;++i) val = apr_table_get(s,k); \
     apr_delta = apr_time_now() - apr_delta; \
     if (v) {CuAssertPtrNotNull(tc,val); CuAssertStrEquals(tc,v,val);} \
     else CuAssertPtrEquals(tc,NULL,val);\
     TEST_DELTAS(apreq,apr,"apr_table_get(" k ") wins"); apr_delta = apr_time_now(); \
  /*   for(i=0;i<LOOP;++i) val = apr_hash_get(h,k,APR_HASH_KEY_STRING);\
     apr_delta = apr_time_now() - apr_delta; \
     if (v) {CuAssertPtrNotNull(tc,val);CuAssertStrEquals(tc,v,val);} \
     else CuAssertPtrEquals(tc,NULL,val); \
     TEST_DELTAS(apreq,apr,"APR hash_get(" k ") wins"); \
  */} while (0)
  
  
  
  #define V(k,v) apreq_make_value(p,k,strlen(k),v,strlen(v))
  #define VV(k)  { #k, 0, 1, 0 }
  
  static char *headers[12] = {"Host", "User-Agent", "Accept",
                              "Accept-Language", "Accept-Encoding",
                              "Accept-Charset", "Keep-Alive",
                              "Connection", "Referer", "Cookie",
                              "Content-Type", "Content-Length"};
  
  static apreq_table_t *init_apreq(int N)
  {
      apreq_table_t *t = apreq_table_make(p,N);
      int j;
      static apreq_value_t v[] = { VV(Host), VV(User-Agent), VV(Accept),
                                   VV(Accept-Language), VV(Accept-Encoding),
                                   VV(Accept-Charset), VV(Keep-Alive),
                                   VV(Connection), VV(Referer), VV(Cookie),
                                   VV(Content-Type), VV(Content-Length) };
      for (j = 0; j < 12; ++j)
          apreq_table_add(t,v + j);
  
      return t;
  }
  
  static apr_table_t *init_apr(int N)
  {
      apr_table_t *t = apr_table_make(p,N);
      int j;
  
      for (j=0; j < 12; ++j)
          apr_table_addn(t, headers[j], "");
  
      return t;
  }
  
  
  static apr_hash_t *init_hash(void)
  {
      apr_hash_t *h = apr_hash_make(p);
      int j;
  
      for (j = 0; j < 12; ++j) {
          const char *k = headers[j];
          int klen = strlen(k);
          const char *v = apr_hash_get(h, k, klen);
          if (v == NULL)
              apr_hash_set(h, k, klen, "");
          else 
              apr_hash_set(h, k, klen, apr_pstrcat(p,v,", ", k, NULL));
      }
      return h;
  }
  
  
  /* measures httpd server's request header initialization time */
  static void perf_init(CuTest *tc)
  {
      apr_time_t apreq_delta,apr_delta;
      int i;
  
      apreq_delta = apr_time_now();
      for (i=0; i<LOOP;++i) {
          apreq_table_t *t = init_apreq(APREQ_NELTS*2);
          apreq_table_normalize(t);
      }
      apreq_delta = apr_time_now() - apreq_delta;
  
      apr_delta = apr_time_now();
      for (i=0; i<LOOP;++i) {
         apr_table_t *t = apr_table_make(p,APREQ_NELTS*2);
         apr_table_t *s = init_apr(APREQ_NELTS*2);
         apr_table_overlap(t,s,APR_OVERLAP_TABLES_MERGE);
      }
      apr_delta = apr_time_now() - apr_delta;
  
      TEST_DELTAS(apreq,apr,"apreq should win");
  
      apr_delta = apr_time_now();
      for (i=0; i<LOOP;++i) {
          apr_hash_t *h = init_hash();
      }
      apr_delta = apr_time_now() - apr_delta;
  
      TEST_DELTAS(apr,apreq,"apr_hash should win");
  }
  
  
  #define GET_AVG(N) \
      apr_delta = apr_time_now(); \
      for (j = 0; j < LOOP; ++j) { \
          const char *val = apr_table_get(s, headers[j % N]); \
          CuAssertPtrNotNull(tc, val); \
      } \
      apr_delta = apr_time_now() - apr_delta; \
      apreq_delta = apr_time_now(); \
      for (j = 0; j < LOOP; ++j) { \
          const char *val = apreq_table_get(t, headers[j % N]); \
          CuAssertPtrNotNull(tc, val); \
      } \
      apreq_delta = apr_time_now() - apreq_delta;
  
  static void perf_get_avg(CuTest *tc)
  {
      apr_table_t *s = init_apr(APREQ_NELTS);
      apreq_table_t *t = init_apreq(APREQ_NELTS);
      apr_time_t apr_delta, apreq_delta;
      int j;
  
      GET_AVG (2); TEST_DELTAS(apr,apreq,"apr_tables should win (2)");
      GET_AVG (4); TEST_DELTAS(apr,apreq,"apr_tables should win (4)");
      GET_AVG (6); TEST_DELTAS(apreq,apr,"apreq should win (6)");
      GET_AVG (8); TEST_DELTAS(apreq,apr,"apreq should win (8)");
      GET_AVG(10); TEST_DELTAS(apreq,apr,"apreq should win (10)");
      GET_AVG(12); TEST_DELTAS(apreq,apr,"apreq should win (12)");
  }
  
  
  /*
   *                         nontrivial trees
   *                        ------------------ 
   *
   *     (4) Accept-Encoding                     (7) Connection
   *         /        \                              /        \
   * (2) Accept  Accept-Language (3)          (9) Cookie   Content-Type (10)
   *         \                                                /
   *    (5) Accept-Charset                             Content-Length (11)
   */
  
  
  static void perf_get(CuTest *tc)
  {
      apr_hash_t *h = init_hash();
      apr_table_t *s = init_apr(APREQ_NELTS);
      apreq_table_t *t = init_apreq(APREQ_NELTS);
      apr_time_t apr_delta, apreq_delta;
      int j;
  
      /* expected apr winners: "Accept", "Connection" "Cookie" */
      /* expected apreq winners: */
      RUN_GET("Accept-Encoding","");
      RUN_GET("Accept-Charset","");
      RUN_GET("Accept-Language","");
      RUN_GET("Content-Length","");
      RUN_GET("Content-Type","");   /* apr wins by .05 microseconds now */
  }
  
  
  #ifdef footoo
  static void table_set(CuTest *tc)
  {
      const char *val;
      apreq_table_t *t = init_apreq(APREQ_NELTS);
      apr_table_t *s = init_apr(APREQ_NELTS);
      apreq_table_set(t1, V("setkey","bar"));
  
      apreq_table_set(t1, V("setkey","2ndtry"));
      val = apreq_table_get(t1,"setkey");
      CuAssertStrEquals(tc,"2ndtry",val);
  
  }
  
  static void table_getnotthere(CuTest *tc)
  {
      const char *val;
  
      val = apreq_table_get(t1, "keynotthere");
      CuAssertPtrEquals(tc, NULL,val);
  }
  
  static void table_add(CuTest *tc)
  {
      const char *val;
  
      apreq_table_add(t1, V("add", "bar"));
      apreq_table_add(t1, V("add", "foo"));
      val = apreq_table_get(t1, "add");
      CuAssertStrEquals(tc, "bar", val);
  
  
      apreq_table_add(t1, V("f", "top"));
      apreq_table_add(t1, V("fo", "child"));
      apreq_table_add(t1, V("fro", "child-right"));
      apreq_table_add(t1, V("foo", "bar"));
  
      /*
       *     f(5)  black                fo(6) black   
       *      fo(6)  red       =>  f(5)red   fro(7)red
       *       fro(7) red
       *
       */
  
  
      apreq_table_add(t1, V("flo", "child-left"));
      apreq_table_add(t1, V("flr", "child-left-right"));
      apreq_table_add(t1, V("frr", "child-right-right"));
      apreq_table_add(t1, V("frl", "child-right-left"));
      apreq_table_add(t1, V("flr", "child-left-right"));
      apreq_table_add(t1, V("fll", "child-left-left"));
  
      apreq_table_add(t1, V("foot", "bart"));
      apreq_table_add(t1, V("foon", "barn"));
      apreq_table_add(t1, V("foot", "bart"));
      apreq_table_add(t1, V("foop", "barp"));
      apreq_table_add(t1, V("food", "bard"));
      apreq_table_add(t1, V("foof", "barf"));
      apreq_table_add(t1, V("fooz", "barz"));
      apreq_table_add(t1, V("fooq", "barq"));
      apreq_table_add(t1, V("foot", "bart"));
      apreq_table_add(t1, V("fooj", "barj"));
      apreq_table_add(t1, V("fook", "bark"));
      apreq_table_add(t1, V("fool", "barl"));
      apreq_table_add(t1, V("foor", "barr"));
      apreq_table_add(t1, V("foos", "bars"));
  
      apreq_table_add(t1, V("foot", "bart"));
      apreq_table_add(t1, V("foon", "barn"));
      apreq_table_add(t1, V("foot", "bart"));
      apreq_table_add(t1, V("foop", "barp"));
      apreq_table_add(t1, V("food", "bard"));
      apreq_table_add(t1, V("foof", "barf"));
      apreq_table_add(t1, V("fooz", "barz"));
      apreq_table_add(t1, V("fooq", "barq"));
      apreq_table_add(t1, V("foot", "bart"));
      apreq_table_add(t1, V("fooj", "barj"));
      apreq_table_add(t1, V("fook", "bark"));
      apreq_table_add(t1, V("fool", "barl"));
      apreq_table_add(t1, V("foor", "barr"));
      apreq_table_add(t1, V("foos", "bars"));
  
      apreq_table_add(t1, V("quux", "quux"));
      apreq_table_add(t1, V("quuxa", "quuxa"));
      apreq_table_add(t1, V("quuxz", "quuxz"));
      apreq_table_add(t1, V("quuxb", "quuxb"));
      apreq_table_add(t1, V("quuxg", "quuxg"));
      apreq_table_add(t1, V("quuxw", "quuxw"));
      apreq_table_add(t1, V("quuxr", "quuxr"));
      apreq_table_add(t1, V("alpha", "omega"));
  
      val = apreq_table_get(t1, "foo");
      CuAssertStrEquals(tc, "bar", val);
      val = apreq_table_get(t1, "quuxb");
      CuAssertStrEquals(tc, "quuxb", val);
      val = apreq_table_get(t1,"flo");
      CuAssertStrEquals(tc, "child-left", val);
  }
  
  static void table_unset(CuTest *tc) {
      const char *val;
      apreq_table_unset(t1, "flo");
      val = apreq_table_get(t1, "flo");
      CuAssertPtrEquals(tc, NULL, val);
  
      val = apreq_table_get(t1, "fro");
      CuAssertStrEquals(tc, "child-right", val);
      val = apreq_table_get(t1, "fll");
      CuAssertStrEquals(tc, "child-left-left", val);
      val = apreq_table_get(t1, "frl");
      CuAssertStrEquals(tc, "child-right-left", val);
  
  }
  
  
  static void table_perf(CuTest *tc)
  {
      CuAssertStrEquals(tc, "quuxb", apreq_table_get(t1,"quuxb"));
  
      RUN_GET("alpha", "omega", "APR wins worst-case scenario");
      RUN_GET("quuxb", "quuxb", "APR wins multi-key case 1");
      RUN_GET("quuxw", "quuxw", "APR wins multi-key case 2");
      RUN_GET("foonot", NULL,   "APR wins missing-key case");
  }
  
  static void table_perf2(CuTest *tc)
  {
      RUN_GET("fool",  "barl",  "APR wins multi-key case 3");
      RUN_GET(APREQ_URL_ENCTYPE, "foo","APR wins triple-key case");
      RUN_GET(APREQ_MFD_ENCTYPE, "bar","APR wins single-key case");
  }
  
  static void table_cache(CuTest *tc)
  {
      apr_table_t *t2 = apreq_table_export(p,t1);
      apr_time_t start, apr_delta, apreq_delta;
      const char *val;
      int i;
  
      start = apr_time_now();
      for (i = 0; i < LOOP; ++i)
          val = apr_table_get(t2, "foo");
      apr_delta = apr_time_now() - start;
      CuAssertStrEquals(tc, "bar", val);
      start = apr_time_now();
      for (i = 0; i < LOOP; ++i)
          val = apreq_table_get(t1, "foo");
      apreq_delta = apr_time_now() - start;
      CuAssertStrEquals(tc, "bar", val);
  
  //    CuAssertTrue(tc, apreq_delta > apr_delta);
  
      /* apr_tables should win (above), since foo is the first "f" item;
       * but it should lose to apreq_tables when cacheing is enabled (below).
       */
      CuAssertStrEquals(tc, "bar", apreq_table_cache(t1,"foo"));
      start = apr_time_now();
      for (i = 0; i < LOOP; ++i)
          val = apreq_table_get(t1, "foo");
      apreq_delta = apr_time_now() - start;
      CuAssertStrEquals(tc, "bar", val);
  
      TEST_DELTAS("APR beats apreq's cache");
  }
  
  static void table_nelts(CuTest *tc)
  {
      const char *val;
      apreq_table_t *t = apreq_table_make(p, 1);
  
  
      apreq_table_set(t, V("abc", "def"));
      apreq_table_set(t, V("def", "abc"));
      apreq_table_set(t, V("foo", "zzz"));
      val = apreq_table_get(t, "foo");
      CuAssertStrEquals(tc, val, "zzz");
  
      val = apreq_table_get(t, "abc");
      CuAssertStrEquals(tc, val, "def");
      val = apreq_table_get(t, "def");
      CuAssertStrEquals(tc, val, "abc");
      CuAssertIntEquals(tc, 3, apreq_table_nelts(t));
  }
  
  static void table_clear(CuTest *tc)
  {
      apreq_table_clear(t1);
      CuAssertIntEquals(tc, 0, apreq_table_nelts(t1));
  }
  
  static void table_overlap(CuTest *tc)
  {
      const char *val;
      apreq_table_t *t2 = init_apreq(APREQ_NELTS);
      apr_table_t *r1, *r2;
      apr_status_t s;
      apr_time_t start, apreq_delta, apr_delta;
      t1 = apreq_table_make(p, APREQ_NELTS);
  
      r1 = apreq_table_export(p,t1);
      r2 = apreq_table_export(p,t2);
  
     /* APR_OVERLAP_TABLES_SET had funky semantics, so we ignore it here */
  
      start = apr_time_now();
      s = apreq_table_overlap(t1, t2, APR_OVERLAP_TABLES_MERGE);
      apreq_delta = apr_time_now() - start;
      CuAssertIntEquals(tc, APR_SUCCESS, s);
      CuAssertIntEquals(tc, 12, apreq_table_nelts(t1));
      start = apr_time_now();
      apr_table_overlap(r1, r2, APR_OVERLAP_TABLES_MERGE);
      apr_delta = apr_time_now() - start;
      CuAssertIntEquals(tc, 12, apr_table_elts(r1)->nelts);
  
      if (apr_delta < apreq_delta)
          CuFail(tc, apr_psprintf(p, "APR wins overlap contest #1: %" APR_INT64_T_FMT
                     " < %" APR_INT64_T_FMT " (microseconds)", apr_delta,apreq_delta));
  
      t1 = apreq_table_make(p, 1);
      t2 = apreq_table_make(p,1);
      apreq_table_add(t1, V("a", "0"));
      apreq_table_add(t1, V("g", "7"));
  
      apreq_table_add(t2, V("a", "1"));
      apreq_table_add(t2, V("b", "2"));
      apreq_table_add(t2, V("c", "3"));
      apreq_table_add(t2, V("b", "2.0"));
      apreq_table_add(t2, V("d", "4"));
      apreq_table_add(t2, V("e", "5"));
      apreq_table_add(t2, V("b", "2."));
      apreq_table_add(t2, V("f", "6"));
  
      r1 = apreq_table_export(p,t1);
      r2 = apreq_table_export(p,t2);
   
     /* APR_OVERLAP_TABLES_SET had funky semantics, so we ignore it here */
  
      val = apreq_table_get(t1, "a");
      CuAssertStrEquals(tc, "0",val);
  
      start = apr_time_now();
      s = apreq_table_overlap(t1, t2, APR_OVERLAP_TABLES_MERGE);
      apreq_delta = apr_time_now() - start;
      CuAssertIntEquals(tc, APR_SUCCESS, s);
      CuAssertIntEquals(tc, 7, apreq_table_nelts(t1));
      start = apr_time_now();
      apr_table_overlap(r1, r2, APR_OVERLAP_TABLES_MERGE);
      apr_delta = apr_time_now() - start;
      CuAssertIntEquals(tc, 7, apr_table_elts(r1)->nelts);
  
  
      if (apr_delta < apreq_delta)
          CuFail(tc, apr_psprintf(p, "APR wins overlap contest #2: %" APR_INT64_T_FMT
                     " < %" APR_INT64_T_FMT " (microseconds)", apr_delta,apreq_delta));
  
  
      t2 = apreq_table_copy(p,t1);
  
      CuAssertIntEquals(tc, 3, apreq_table_ghosts(t2));
      CuAssertIntEquals(tc, 9, apreq_table_exorcise(t2));
      CuAssertIntEquals(tc, 0, apreq_table_ghosts(t2));
      CuAssertIntEquals(tc, 7, apreq_table_nelts(t2));
  
      val = apreq_table_get(t2, "a");
      CuAssertStrEquals(tc, "0, 1",val);
      val = apreq_table_get(t2, "b");
      CuAssertStrEquals(tc, "2, 2.0, 2.",val);
      val = apreq_table_get(t2, "c");
      CuAssertStrEquals(tc, "3",val);
      val = apreq_table_get(t2, "d");
      CuAssertStrEquals(tc, "4",val);
      val = apreq_table_get(t2, "e");
      CuAssertStrEquals(tc, "5",val);
      val = apreq_table_get(t2, "f");
      CuAssertStrEquals(tc, "6",val);
      val = apreq_table_get(t2, "g");
      CuAssertStrEquals(tc, "7",val);
  
  }
  
  #define APREQ_ELT(a,i) (*(apreq_value_t **)((a)->elts + (i) * (a)->elt_size))
  
  static void table_elts(CuTest *tc)
  {
      const char *val;
      const apreq_value_t *v;
      const apr_array_header_t *a;
  
      CuAssertIntEquals(tc, 7, apreq_table_nelts(t1));
      CuAssertIntEquals(tc, 3, apreq_table_ghosts(t1));
  
      a = apreq_table_elts(t1);
  
      CuAssertIntEquals(tc, 7, apreq_table_nelts(t1));
      CuAssertIntEquals(tc, 0, apreq_table_ghosts(t1));
  
      v = APREQ_ELT(a,0);
      CuAssertStrEquals(tc,"0, 1", v->data);
      v = APREQ_ELT(a,1);
      CuAssertStrEquals(tc,"7", v->data);
      v = APREQ_ELT(a,2);
      CuAssertStrEquals(tc,"2, 2.0, 2.", v->data);
      v = APREQ_ELT(a,3);
      CuAssertStrEquals(tc,"3", v->data);
  
      v = APREQ_ELT(a,a->nelts-1);
      CuAssertStrEquals(tc,"6", v->data);
      v = APREQ_ELT(a,a->nelts-2);
      CuAssertStrEquals(tc,"5", v->data);
      v = APREQ_ELT(a,a->nelts-3);
      CuAssertStrEquals(tc,"4", v->data);
  
  }
  
  static void table_overlay(CuTest *tc)
  {
      const char *val;
      apreq_table_t *t2 = apreq_table_make(p, 1);
      apr_status_t s;
  
      t1 = apreq_table_make(p, 1);
  
      apreq_table_add(t1, V("a", "0"));
      apreq_table_add(t1, V("g", "7"));
  
      apreq_table_add(t2, V("a", "1"));
      apreq_table_add(t2, V("b", "2"));
      apreq_table_add(t2, V("c", "3"));
      apreq_table_add(t2, V("b", "2.0"));
      apreq_table_add(t2, V("d", "4"));
      apreq_table_add(t2, V("e", "5"));
      apreq_table_add(t2, V("b", "2."));
      apreq_table_add(t2, V("f", "6"));
      t1 = apreq_table_overlay(p, t1, t2);
  
      CuAssertIntEquals(tc, 10, apreq_table_nelts(t1));
  
      val = apreq_table_get(t1, "a");
      CuAssertStrEquals(tc, "0",val);
      val = apreq_table_get(t1, "b");
      CuAssertStrEquals(tc, "2",val);
      val = apreq_table_get(t1, "c");
      CuAssertStrEquals(tc, "3",val);
      val = apreq_table_get(t1, "d");
      CuAssertStrEquals(tc, "4",val);
      val = apreq_table_get(t1, "e");
      CuAssertStrEquals(tc, "5",val);
      val = apreq_table_get(t1, "f");
      CuAssertStrEquals(tc, "6",val);
      val = apreq_table_get(t1, "g");
      CuAssertStrEquals(tc, "7",val);
  }
  
  static void table_keys(CuTest *tc)
  {
      const char *k;
      apr_array_header_t *a = apr_array_make(p,1, sizeof k);
      apr_status_t s = apreq_table_keys(t1,a);
  
      CuAssertIntEquals(tc, APR_SUCCESS, s);
      CuAssertIntEquals(tc, 7, a->nelts);
      k = ((const char **)a->elts)[0];
      CuAssertStrEquals(tc, "a", k);
      k = ((const char **)a->elts)[1];
      CuAssertStrEquals(tc, "g", k);
      k = ((const char **)a->elts)[2];
      CuAssertStrEquals(tc, "b", k);
      k = ((const char **)a->elts)[3];
      CuAssertStrEquals(tc, "c", k);
      k = ((const char **)a->elts)[4];
      CuAssertStrEquals(tc, "d", k);
      k = ((const char **)a->elts)[5];
      CuAssertStrEquals(tc, "e", k);
      k = ((const char **)a->elts)[6];
      CuAssertStrEquals(tc, "f", k);
  }
  
  static void table_values(CuTest *tc)
  {
      const apreq_value_t *v;
      apr_array_header_t *a = apr_array_make(p,1,sizeof v);
      apr_status_t s = apreq_table_values(t1,"a",a);
      CuAssertIntEquals(tc, APR_SUCCESS, s);
      CuAssertIntEquals(tc, 2, a->nelts);
      v = ((const apreq_value_t **)a->elts)[0];
      CuAssertStrEquals(tc, "a", v->name);
      CuAssertStrEquals(tc, "0", v->data);
      v = ((const apreq_value_t **)a->elts)[1];
      CuAssertStrEquals(tc, "a", v->name);
      CuAssertStrEquals(tc, "1", v->data);
      a->nelts = 0;
      s = apreq_table_values(t1,"b",a);
      CuAssertIntEquals(tc, APR_SUCCESS, s);
      CuAssertIntEquals(tc, 3, a->nelts);
      v = ((const apreq_value_t **)a->elts)[0];
      CuAssertStrEquals(tc, "b", v->name);
      CuAssertStrEquals(tc, "2", v->data);
      v = ((const apreq_value_t **)a->elts)[1];
      CuAssertStrEquals(tc, "b", v->name);
      CuAssertStrEquals(tc, "2.0", v->data);
      v = ((const apreq_value_t **)a->elts)[2];
      CuAssertStrEquals(tc, "b", v->name);
      CuAssertStrEquals(tc, "2.", v->data);
  
      a->nelts = 0;
      s = apreq_table_values(t1,NULL,a);
      CuAssertIntEquals(tc, APR_SUCCESS, s);
      CuAssertIntEquals(tc, 7, a->nelts);
      
  }
  #endif
  
  CuSuite *testperformance(void)
  {
      CuSuite *suite = CuSuiteNew("Performance");
  
      SUITE_ADD_TEST(suite, perf_init);
      SUITE_ADD_TEST(suite, perf_get_avg); 
      SUITE_ADD_TEST(suite, perf_get); 
  /*
      SUITE_ADD_TEST(suite, table_set);
      SUITE_ADD_TEST(suite, table_getnotthere);
      SUITE_ADD_TEST(suite, table_add);
      SUITE_ADD_TEST(suite, table_unset);
      SUITE_ADD_TEST(suite, table_perf);
      SUITE_ADD_TEST(suite, table_perf2);
      SUITE_ADD_TEST(suite, table_cache);
      SUITE_ADD_TEST(suite, table_nelts);
      SUITE_ADD_TEST(suite, table_clear);
      SUITE_ADD_TEST(suite, table_overlap);
      SUITE_ADD_TEST(suite, table_elts);
      SUITE_ADD_TEST(suite, table_overlay);
      SUITE_ADD_TEST(suite, table_keys);
      SUITE_ADD_TEST(suite, table_values);
  */
      return suite;
  }
  
  
  
  

Mime
View raw message