joes        2003/04/28 07:05:01

  Modified:    src      apreq_tables.c
  Log:
  Adopt Weiss' single-pass insertion for red-black trees.  Included some 
reference urls in the source.
  
  Revision  Changes    Path
  1.23      +235 -204  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.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- apreq_tables.c    26 Apr 2003 20:55:34 -0000      1.22
  +++ apreq_tables.c    28 Apr 2003 14:05:01 -0000      1.23
  @@ -77,13 +77,13 @@
       const char          *key;   /* = val->name : saves a ptr deref */
   
       enum { RED, BLACK }  color;
  -    int                  tree[4];  /* LEFT RIGHT PARENT NEXT */
  +    int                  tree[4];  /* LEFT RIGHT UP NEXT */
   } apreq_table_entry_t;
   
   /* LEFT & RIGHT must satisfy !LEFT==RIGHT , !RIGHT==LEFT */
   #define LEFT   0
   #define RIGHT  1
  -#define PARENT 2
  +#define UP     2
   #define NEXT   3
   
   
  @@ -100,18 +100,12 @@
   
   
   /* XXX: apreq_tables need to be signal( thread? )safe; currently
  -   these LOCK* macros indicate some unsafe locations in the code. */
  +   these LOCK* macros might indicate some unsafe locations in the code. */
   
  -/* coarse locking (maybe API worthy) */
   #define LOCK_TABLE(t)
   #define UNLOCK_TABLE(t)
   #define TABLE_IS_LOCKED(t)
   
  -/* finer grained tree locks (internal) */
  -#define LOCK_TREE(t,n)
  -#define UNLOCK_TREE(t,n)
  -#define TREE_IS_LOCKED(t,n)
  -
   #define TF_BALANCE   1
   #define TF_LOCK      2
   
  @@ -132,24 +126,30 @@
   
   
   #define DEAD(idx)     ( (idx)[o].key == NULL )
  -#define KILL(t,idx) do { (idx)[o].key = NULL; \
  -                         if ((idx)==(t)->a.nelts-1) (t)->a.nelts--; \
  -                         else                       (t)->ghosts++; } while 
(0)
  +#define KILL(t,idx)    do { (idx)[o].key = NULL; \
  +                            (t)->ghosts++; } while (0)
   #define RESURRECT(t,idx) do { (idx)[o].key = (idx)[o].val->name; \
                                 (t)->ghosts--; } while (0)
   
   /* NEVER KILL AN ENTRY THAT'S STILL WITHIN THE FOREST */
  -#define IN_FOREST(t,idx) ( !DEAD(idx) && ( (idx)[o].tree[PARENT] >= 0 || \
  +#define IN_FOREST(t,idx) ( !DEAD(idx) && ( (idx)[o].tree[UP] >= 0 || \
                              (idx) == t->root[TABLE_HASH((idx)[o].key)] ) )
   
  -/********************* (internal) tree operations ********************/
  +/* MUST ensure n's parent exists (>=0) before using LR(n) */
  +#define LR(n) (  ( (n)[o].tree[UP][o].tree[LEFT] == (n) ) ? LEFT : RIGHT  )
   
  +#define PROMOTE(r,p)  do rotate(o,r,o[p].tree[UP],!LR(p)); \
  +                         while (o[p].tree[UP] >= 0)
   
  -/* MUST ensure n's parent exists (>=0) before using LR(n) */
  -#define LR(n) (  ( (n)[o].tree[PARENT][o].tree[LEFT] == (n) ) ? LEFT : RIGHT 
 )
  +/********************* (internal) tree operations ********************
  + *
  + * good general references for binary tree algorithms:
  + *
  + * Ben Pfaff's book on libavl 2.0:
  + *      http://www.msu.edu/user/pfaffben/avl/
  + *
  + */
   
  -#define PROMOTE(o,r,p)  do rotate(o,r,o[p].tree[PARENT],!LR(p)); \
  -                           while (o[p].tree[PARENT] >= 0)
   
   /**
    *       pivot                            child
  @@ -166,25 +166,33 @@
                                 const int direction)
   {
       const int child   = pivot[o].tree[!direction];
  -    const int parent  = pivot[o].tree[PARENT];
  +    const int parent  = pivot[o].tree[UP];
   
       pivot[o].tree[!direction] = child[o].tree[direction];
   
       if (pivot[o].tree[!direction] >= 0)
  -        pivot[o].tree[!direction][o].tree[PARENT] = pivot;
  +        pivot[o].tree[!direction][o].tree[UP] = pivot;
   
       if (parent >= 0)
           parent[o].tree[LR(pivot)] = child;
       else
           *root = child;
   
  -    child[o].tree[PARENT]      = parent;
  -    child[o].tree[direction]   = pivot;
  -    pivot[o].tree[PARENT]      = child;
  +    child[o].tree[UP]        = parent;
  +    child[o].tree[direction] = pivot;
  +    pivot[o].tree[UP]        = child;
   
   }
   
   
  +/*
  + * puts location of "nearest" index in *elt
  + * returns 0 if key is found, otherwise the return value's
  + * sign represents the direction (LEFT <0, RIGHT >0) to move 
  + * from elt.   This is where the key "should" be located
  + * were it added to the tree.
  + *
  + */
   static APR_INLINE int search(apreq_table_entry_t *o, 
                                int *elt,
                                const char *key) 
  @@ -192,6 +200,7 @@
       int idx = *elt;
       if ( idx < 0)
           return 0;
  +
       while (1) {
           int direction = strcasecmp(key,idx[o].key);
   
  @@ -208,12 +217,68 @@
   }
   
   
  +/* 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 )
   {
       int idx = elt - o;
  -    int s = search(o, &x, elt->key);
  +    int s;
  +
  +#define REBALANCE do {                                  \
  +    int parent = x[o].tree[UP];                         \
  +    x[o].color == RED;                                  \
  +    if (parent >= 0 && parent[o].color == RED) {        \
  +        int parent_direction = LR(parent);              \
  +        int grandparent = parent[o].tree[UP];           \
  +        if (parent_direction != LR(x)) {                \
  +            rotate(o, root, parent, parent_direction);  \
  +            parent = x;                                 \
  +        }                                               \
  +        parent[o].color = BLACK;                        \
  +        grandparent[o].color = RED;                     \
  +        rotate(o, root, grandparent, !parent_direction);\
  +    } (*root)[o].color = BLACK; } while (0)
  +
  +  
  +    if (flags & TF_BALANCE && *root != -1) {
  +        /*
  +         * 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
  +         */
  +        while (1) {
  +            int left = x[o].tree[LEFT];
  +            int right = x[o].tree[RIGHT];
  +
  +            s = strcasecmp(elt->key,x[o].key);
  +
  +            if (s < 0 && left >= 0) {
  +                if (left[o].color == RED && right >= 0 
  +                    && right[o].color == RED)
  +                {
  +                    left[o].color = right[o].color = BLACK;
  +                    REBALANCE;
  +                }
  +                x = left;
  +            }
  +            else if (s > 0 && right >= 0) {
  +                if (right[o].color == RED && left >= 0 
  +                    && left[o].color == RED)
  +                {
  +                    left[o].color = right[o].color = BLACK;
  +                    REBALANCE;
  +                }
  +                x = right;
  +            }
  +            else
  +                break;
  +        }
  +    }
  +    else
  +        s = search(o, &x, elt->key);
   
       if (s == 0) { /* found */
           int parent = x;
  @@ -221,8 +286,8 @@
               *root = idx;
               elt->tree[LEFT]   = -1;
               elt->tree[RIGHT]  = -1;
  -            elt->tree[PARENT] = -1;
  -            elt->color = BLACK;
  +            elt->tree[UP]     = -1;
  +            elt->color        = BLACK;
               return -1;
           }
   
  @@ -231,10 +296,10 @@
           while (parent[o].tree[NEXT] >= 0)
               parent = parent[o].tree[NEXT];
   
  -        parent[o].tree[NEXT]   = idx;
  -        elt->tree[PARENT]      = -1;
  -        elt->tree[RIGHT]       = -1;
  -        elt->tree[LEFT]        = -1;
  +        parent[o].tree[NEXT]  = idx;
  +        elt->tree[UP]         = -1;
  +        elt->tree[RIGHT]      = -1;
  +        elt->tree[LEFT]       = -1;
           return x;
       }
   
  @@ -242,46 +307,16 @@
       /* The element wasn't in the tree, so add it */
       x[o].tree[s < 0 ? LEFT : RIGHT] = idx;
   
  -    elt->tree[PARENT] =  x;
  -    elt->tree[RIGHT]  = -1;
  -    elt->tree[LEFT]   = -1;
  -
  +    elt->tree[UP]    =  x;
  +    elt->tree[RIGHT] = -1;
  +    elt->tree[LEFT]  = -1;
       elt->color = RED;
   
       if (flags & TF_BALANCE) {
  -        while (idx[o].tree[PARENT] >= 0 && idx[o].tree[PARENT][o].color == 
RED)
  -        {
  -        /* parent & grandparent exist, parent_sibling may not */
  -
  -            int parent = idx[o].tree[PARENT];
  -            int grandparent = parent[o].tree[PARENT];
  -            register const int parent_direction = LR(parent);
  -            int parent_sibling = grandparent[o].tree[!parent_direction];
  -
  -            if (parent_sibling >= 0 && parent_sibling[o].color == RED) {
  -                parent[o].color            = BLACK;
  -                parent_sibling[o].color    = BLACK;
  -                grandparent[o].color       = RED;
  -                idx                        = grandparent;
  -                parent                     = idx[o].tree[PARENT];
  -            }
  -            else {  /* parent_sibling->color == BLACK */
  -
  -                if ( LR(idx) != parent_direction ) {
  -                    /* demote parent & swap idx with parent */
  -                    rotate(o, root, parent, parent_direction);
  -                    idx           = parent;
  -                    parent        = idx[o].tree[PARENT];
  -                }
  -
  -                /* promote parent */
  -                parent[o].color      = BLACK;
  -                grandparent[o].color = RED;
  -                rotate(o, root, grandparent, !parent_direction);
  -            }
  -        }
  +        x = idx;
  +        REBALANCE;
       }
  -    (*root)[o].color = BLACK;
  +#undef REBALANCE
       return -1;
   }
   
  @@ -290,103 +325,112 @@
                      int *root,  const int idx, unsigned flags)
   {
       int x;
  +    int parent = idx[o].tree[UP];
   
       if (idx[o].tree[LEFT] < 0 || idx[o].tree[RIGHT] < 0) {
           x = 1 + idx[o].tree[RIGHT] + idx[o].tree[LEFT];
   
  -        /* replace idx with x */
  -        if (idx[o].tree[PARENT] >= 0)
  -            idx[o].tree[PARENT][o].tree[LR(idx)] = x;
  +        /* remove idx & promote x */
  +        if (parent >= 0)
  +            parent[o].tree[LR(idx)] = x;
           else
               *root = x;
   
           if (x >= 0)
  -            x[o].tree[PARENT] = idx[o].tree[PARENT];
  +            x[o].tree[UP] = parent;
   
  -        if (idx[o].color == RED)
  +        if (flags & TF_BALANCE == 0 || idx[o].color == RED)
               return;
       }
       else {
  -        /* find idx's in-order successor & remove that instead */
  +        /* find idx's in-order successor & replace idx with it */
           int y = idx[o].tree[RIGHT];
           while (y[o].tree[LEFT] >= 0)
               y = y[o].tree[LEFT];
   
           x = y[o].tree[RIGHT];
   
  -        if (y[o].tree[PARENT] != idx) {
  +        if (y[o].tree[UP] != idx) {
               y[o].tree[RIGHT] = idx[o].tree[RIGHT];
   
               if (x >= 0) {
                   /* replace y with x */
  -                x[o].tree[PARENT] = y[o].tree[PARENT];
  -                y[o].tree[PARENT][o].tree[LR(y)] = x;
  +                x[o].tree[UP]                = y[o].tree[UP];
  +                y[o].tree[UP][o].tree[LR(y)] = x;
               }
           }
   
           /* copy idx's tree data into y ("RIGHT" is already done). */
           y[o].tree[LEFT] = idx[o].tree[LEFT];
  -        y[o].tree[PARENT] = idx[o].tree[PARENT];
  +        y[o].tree[UP]   = idx[o].tree[UP];
   
           /* replace idx with y */
  -        if (idx[o].tree[PARENT] >= 0)
  -            idx[o].tree[PARENT][o].tree[LR(idx)] = y;
  +        if (parent >= 0)
  +            parent[o].tree[LR(idx)] = y;
           else
               *root = y;
   
  -        if (y[o].color == RED) {
  +        if (flags & TF_BALANCE == 0 || y[o].color == RED) {
               y[o].color = idx[o].color;
               return;
           }
           else
               y[o].color = idx[o].color;
  -
       }
   
  -    /* rebalance tree (standard double-black promotion) */
   
  -    if (flags & TF_BALANCE) {
  -        while (x != *root && x[o].color == BLACK) {
  -            /* x has a grandparent, parent & sibling */
  -            int parent = x[o].tree[PARENT];
  -            int grandparent = parent[o].tree[PARENT];
  -            register const int direction = LR(x);
  -            int sibling = parent[o].tree[!direction];
  -
  -            if (sibling[o].color == RED) {
  -                sibling[o].color = BLACK;
  -                parent[o].color  = RED;
  -                rotate(o, root, parent, !direction); /* demote x */
  -                grandparent = sibling;
  -                sibling = parent[o].tree[!direction];
  -            }
  +    /* Rebalance tree to deal with violations of 
  +     * black node count via standard double-black promotion.
  +     * online ref:
  +     * Bruce Schneier's 1992 DDJ article:
  +     *      http://www.ddj.com/documents/s=1049/ddj9204c/9204c.htm
  +     *
  +     */
  +
  +    while (x[o].color == BLACK && x != *root) {
  +        /* x has a parent & sibling */
  +        int parent = x[o].tree[UP];
  +        register const int direction = LR(x);
  +        int sibling = parent[o].tree[!direction];
  +
  +        if (sibling[o].color == RED) {
  +            sibling[o].color = BLACK;
  +            parent[o].color  = RED;
  +            rotate(o, root, parent, direction); /* promote sibling */
  +            sibling = parent[o].tree[!direction];
  +        }
   
  -            if (sibling[o].tree[direction][o].color == BLACK && 
  -                sibling[o].tree[!direction][o].color == BLACK) 
  -            {
  +        if (sibling[o].tree[direction][o].color == BLACK && 
  +            sibling[o].tree[!direction][o].color == BLACK) 
  +        {
  +            sibling[o].color = RED;
  +            x = parent;
  +        }
  +        else {
  +            if (sibling[o].tree[!direction][o].color == BLACK) {
  +                sibling[o].tree[direction][o].color = BLACK;
                   sibling[o].color = RED;
  -                x = parent;
  -            }
  -            else {
  -                if (sibling[o].tree[!direction][o].color == BLACK) {
  -                    sibling[o].tree[direction][o].color = BLACK;
  -                    sibling[o].color = RED;
  -                    rotate(o, root, sibling, !direction); /* demote sibling 
*/
  -                    sibling = parent[o].tree[!direction];
  -                }
  -                sibling[o].color = parent[o].color;
  -                parent[o].color = BLACK;
  -                sibling[o].tree[!direction][o].color = BLACK;
  -                rotate(o, root, parent, direction); /* promote x */
  -                *root = x;
  +                rotate(o, root, sibling, !direction); /* demote sibling */
  +                sibling = parent[o].tree[!direction];
               }
  +            sibling[o].color = parent[o].color;
  +            parent[o].color = BLACK;
  +            sibling[o].tree[!direction][o].color = BLACK;
  +            rotate(o, root, parent, direction); /* promote sibling */
  +            x = *root;
           }
  -        x[o].color = BLACK;
       }
  +    x[o].color = BLACK;
   }
   
  -static int combine(apreq_table_entry_t *o, int a, 
  -                   int b, const int n)
  +/*
  + * Recursive function that combines two trees by root-inserting
  + * the elements of the second (b) into the first (a).  Note that 
  + * elements of the second tree must also be reindexed since their 
  + * origin is n entries away from a's origin (o).
  + *
  + */
  +static int combine(apreq_table_entry_t *o, int a, int b, const int n)
   {
       int left, right, next;
   
  @@ -402,28 +446,29 @@
           next[o].tree[NEXT] += n;
   
       if (a >= 0) {
  -        int rv = a;
  -        int parent = a[o].tree[PARENT];
  +        int rv     = a;
  +        int parent = a[o].tree[UP];
  +
           if (parent >= 0) {
  -            parent[o].tree[LR(a)] = b;
  -            a[o].tree[PARENT] = -1;
  +            parent[o].tree[LR(a)] =  b;
  +            a[o].tree[UP]         = -1;
           }
   
  -        if (insert(o,&a,a,b+o,0) < 0)
  +        if (insert(o,&a,a,b+o,0) < 0) /* b is a new element for a's tree */
               rv = b;
   
  -        if (b[o].tree[PARENT] >= 0)
  -            PROMOTE(o,&a,b);
  +        if (b[o].tree[UP] >= 0)
  +            PROMOTE(&a,b);
   
  -        b[o].tree[PARENT] = parent;
  +        b[o].tree[UP]    = parent;
           b[o].tree[LEFT]  = combine(o, b[o].tree[LEFT],  left,  n);
           b[o].tree[RIGHT] = combine(o, b[o].tree[RIGHT], right, n);
   
           return rv;
       }
       else {
  -        if (b[o].tree[PARENT] >= 0)
  -            b[o].tree[PARENT] += n;
  +        if (b[o].tree[UP] >= 0)
  +            b[o].tree[UP] += n;
           b[o].tree[LEFT]  = combine(o, -1,  left, n);
           b[o].tree[RIGHT] = combine(o, -1, right, n);
   
  @@ -438,10 +483,6 @@
    * The "apreq_table" API.
    */
   
  -
  -/* static void make_array_core(apr_array_header_t *res, apr_pool_t *p,
  -                         int nelts, int elt_size, int clear) */
  -
   #define make_array_core(a,p,n,s,c) do {        \
       if (c)                                     \
           (a)->elts = apr_pcalloc(p, (n) * (s)); \
  @@ -455,15 +496,8 @@
   
   #define v2c(ptr) ( (ptr) ? (ptr)->data : NULL )
   
  -/*
  - * XXX: if you tweak this you should look at is_empty_table() and 
table_elts()
  - * in alloc.h
  - */
  -
   static void *apr_array_push_noclear(apr_array_header_t *arr)
   {
  -    /* XXX: this function is not reentrant */
  -
       if (arr->nelts == arr->nalloc) {
           int new_size = (arr->nalloc <= 0) ? 1 : arr->nalloc * 2;
           char *new_data;
  @@ -485,12 +519,6 @@
   /********************* table ctors ********************/
   
   
  -static apreq_value_t *collapse(apr_pool_t *p, 
  -                               const apr_array_header_t *arr)
  -{
  -    apreq_value_t **a = (apreq_value_t **)arr->elts;
  -    return (arr->nelts == 0) ? NULL : a[arr->nelts - 1];
  -}
   
   APREQ_DECLARE(apreq_table_t *) apreq_table_make(apr_pool_t *p, int nelts)
   {
  @@ -508,6 +536,7 @@
       return t;
   }
   
  +
   APREQ_DECLARE(apreq_table_t *) apreq_table_copy(apr_pool_t *p, 
                                                   const apreq_table_t *t)
   {
  @@ -524,6 +553,7 @@
       return new;
   }
   
  +
   APREQ_DECLARE(apr_table_t *)apreq_table_export(apr_pool_t *p,
                                                  const apreq_table_t *t)
   {
  @@ -620,7 +650,9 @@
   
           memset(t->root,-1,TABLE_HASH_SIZE * sizeof(int));
           for (idx = 0; idx < t->a.nelts; ++idx)
  -            insert(o, &t->root[TABLE_HASH(idx[o].key)], -1, &idx[o], 
TF_BALANCE);
  +            if (IN_FOREST(t,idx))
  +                insert(o, &t->root[TABLE_HASH(idx[o].key)], 
  +                       -1, &idx[o], TF_BALANCE);
   
           t->flags |= TF_BALANCE;
       }
  @@ -648,31 +680,27 @@
           if ( j >= 0 && IN_FOREST(t,idx) ) {
               apreq_value_t *v;
   
  -            LOCK_TABLE(t);
               arr.nelts = 0;
   
               *(const apreq_value_t **)apr_array_push(&arr) = idx[o].val;
   
               for ( ; j >= 0; j = j[o].tree[NEXT]) {
  -                *(const apreq_value_t **)apr_array_push(&arr) = j[o].val;
                   KILL(t,j);
  +                *(const apreq_value_t **)apr_array_push(&arr) = j[o].val;
               }
   
               v = t->merge(t->a.pool, &arr);
   
               if (v == NULL) {
                   status = APR_EINCOMPLETE;
  -                for (j = idx[o].tree[NEXT] ; j >= 0; 
  -                     j = j[o].tree[NEXT])
  +                for (j = idx[o].tree[NEXT] ; j >= 0; j = j[o].tree[NEXT])
                       RESURRECT(t,j);
               }
               else {
  -                v->name = idx[o].val->name;
  +                idx[o].key = idx[o].val->name;
                   idx[o].val = v;
                   idx[o].tree[NEXT] = -1;
               }
  -
  -            UNLOCK_TABLE(t);
           }
       }
       return status;
  @@ -689,8 +717,6 @@
       *(int *)apr_array_push(q) = t->a.nelts; 
       q->nelts--;
   
  -    LOCK_TABLE(t);
  -
       /* remove entries O(t->nelts)! */
       for ( j=1, n=0; n < q->nelts; ++j, ++n )
           for (m = p[n]+1; m < p[n+1]; ++m)
  @@ -708,15 +734,14 @@
       }
   
       for ( j=0; j < t->a.nelts; ++j ) {
  -        REINDEX( j[o].tree[LEFT]   );
  -        REINDEX( j[o].tree[RIGHT]  );
  -        REINDEX( j[o].tree[PARENT] );
  -        REINDEX( j[o].tree[NEXT]   );
  +        REINDEX( j[o].tree[LEFT]  );
  +        REINDEX( j[o].tree[RIGHT] );
  +        REINDEX( j[o].tree[UP]    );
  +        REINDEX( j[o].tree[NEXT]  );
       }
   
   #undef REINDEX
   
  -    UNLOCK_TABLE(t);
       return rv;
   }
   
  @@ -772,7 +797,7 @@
   
       if (idx != *root) {
           t->flags &= ~TF_BALANCE;
  -        PROMOTE(o,root,idx);
  +        PROMOTE(root,idx);
       }
       return v2c(idx[o].val);
   }
  @@ -783,7 +808,7 @@
   {
       int idx;
       apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  -    if (t->a.nelts == 0)
  +    if (t->a.nelts == t->ghosts)
           return APR_NOTFOUND;
   
       for (idx = 0; idx < t->a.nelts; ++idx)
  @@ -801,7 +826,7 @@
   {
       int idx;
       apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  -    if (t->a.nelts == 0)
  +    if (t->a.nelts == t->ghosts)
           return APR_NOTFOUND;
   
       if (key == NULL) {  /* fetch all values */
  @@ -822,31 +847,36 @@
   }
   
   
  -APREQ_DECLARE(void) apreq_table_set(apreq_table_t *t, const apreq_value_t 
*val)
  +APREQ_DECLARE(void) apreq_table_set(apreq_table_t *t, 
  +                                    const apreq_value_t *val)
   {
       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;
   
  -    if (idx >= 0 && search(o,&idx,key) == 0) {
  +    e->key = key;
  +    e->val = val;
  +    e->tree[NEXT] = -1;
  +
  +    idx = insert(o,&t->root[TABLE_HASH(key)], idx ,e,t->flags);
  +
  +    if (idx >= 0) {
           int n;
           idx[o].val = val;
   
           for ( n=idx[o].tree[NEXT]; n>=0; n=n[o].tree[NEXT] )
               KILL(t,n);
   
  -        idx[o].tree[NEXT] = -1;        
  -    }
  -    else {
  -        apreq_table_entry_t *e = table_push(t);
  -        e->key = key;
  -        e->val = val;
  -        e->tree[NEXT] = -1;
  -        insert((apreq_table_entry_t *)t->a.elts,
  -               &t->root[TABLE_HASH(key)],idx,e,t->flags);
  +        while (DEAD(t->a.nelts-1)) {
  +            t->ghosts--;
  +            t->a.nelts--;
  +        }
  +        idx[o].tree[NEXT] = -1;
       }
   }
   
  +
   APREQ_DECLARE(void) apreq_table_unset(apreq_table_t *t, const char *key)
   {
       int idx = t->root[TABLE_HASH(key)];
  @@ -854,15 +884,9 @@
   
       if (idx >= 0 && search(o,&idx,key) == 0) {
           int n;
  -
  -        LOCK_TABLE(t);
  -
           delete(o,&t->root[TABLE_HASH(key)],idx, t->flags);
  -
           for ( n=idx; n>=0; n=n[o].tree[NEXT] )
               KILL(t,n);
  -
  -        UNLOCK_TABLE(t);
       }
   }
   
  @@ -872,11 +896,16 @@
   {
       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 *e;
   
  +    e->key = val->name;
  +    e->val = val;
  +    e->tree[NEXT] = -1;
   
  -    if (idx >= 0 && search(o,&idx,val->name) == 0) {
  +    idx = insert(o,&t->root[TABLE_HASH(key)],idx,e,t->flags);
  +
  +    if (idx >= 0) {
           int n;
           apreq_value_t *a[APREQ_NELTS];
           apr_array_header_t arr = { t->a.pool, sizeof(apreq_value_t *), 0,
  @@ -901,17 +930,15 @@
           }
   
           idx[o].val = val;
  +
  +        while (DEAD(t->a.nelts-1)) {
  +            t->ghosts--;
  +            t->a.nelts--;
  +        }
  +
           idx[o].tree[NEXT] = -1;
  -        return val->status;
  -    }
  -    else {
  -        e = table_push(t);
  -        e->key = val->name;
  -        e->val = val;
  -        e->tree[NEXT] = -1;
  -        insert((apreq_table_entry_t *)t->a.elts,
  -               &t->root[TABLE_HASH(key)],idx,e,t->flags);
       }
  +
       return val->status;
   }
   
  @@ -925,6 +952,7 @@
       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);
  @@ -960,8 +988,7 @@
   
       apr_array_cat(&t->a, &s->a);
       o = (apreq_table_entry_t *)t->a.elts;
  -
  -    LOCK_TABLE(t);
  +    t->ghosts += s->ghosts;
   
       if (t->flags & TF_BALANCE) {
           for (idx = n; idx < t->a.nelts; ++idx) {
  @@ -972,35 +999,30 @@
   
               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[PARENT] >= 0)
  -                    idx[o].tree[PARENT] += n;
  +                if (idx[o].tree[UP] >= 0)
  +                    idx[o].tree[UP] += n;
   
                   t->root[hash] = idx;
               }
  -            else if ( idx[o].tree[PARENT] >= 0 || 
  -                      s->root[hash] == idx-n ) 
  -            {
  +            else if ( idx[o].tree[UP] >= 0 || s->root[hash] == idx-n ) 
                   insert(o, &t->root[hash], t->root[hash], idx+o, TF_BALANCE);
  -            }
           }
       }
       else {
           for (idx = 0; idx < TABLE_HASH_SIZE; ++idx)
               t->root[idx] = combine(o,t->root[idx],s->root[idx],n);
       }
  -
  -    UNLOCK_TABLE(t);
   }
   
   APREQ_DECLARE(apreq_table_t *) apreq_table_overlay(apr_pool_t *p,
  -                                                   const apreq_table_t 
*overlay,
  -                                                   const apreq_table_t *base)
  +                                             const apreq_table_t *overlay,
  +                                             const apreq_table_t *base)
   {
       apreq_table_t *t = apr_palloc(p, sizeof *t);
   
  @@ -1008,7 +1030,7 @@
       t->a.elt_size = sizeof(apreq_table_entry_t);
       t->copy = overlay->copy;
       t->merge = overlay->merge;
  -    t->flags = overlay->flags & base->flags;
  +    t->flags = overlay->flags;
       t->ghosts = overlay->ghosts;
   
       memcpy(t->root, overlay->root, TABLE_HASH_SIZE * sizeof(int));
  @@ -1020,7 +1042,7 @@
                                          overlay->a.nelts);
   
       t->a.nelts = overlay->a.nelts;
  -    t->a.nalloc = overlay->a.nelts + base->a.nalloc;
  +    t->a.nalloc = overlay->a.nalloc + base->a.nalloc;
   
       if (base->a.nelts) {
           if (t->a.nelts)
  @@ -1031,6 +1053,15 @@
   
       return t;
   }
  +
  +
  +static apreq_value_t *collapse(apr_pool_t *p, 
  +                               const apr_array_header_t *arr)
  +{
  +    apreq_value_t **a = (apreq_value_t **)arr->elts;
  +    return (arr->nelts == 0) ? NULL : a[arr->nelts - 1];
  +}
  +
   
   APREQ_DECLARE(apr_status_t) apreq_table_overlap(apreq_table_t *a, 
                                                   const apreq_table_t *b,
  
  
  

Reply via email to