perl-modperl-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ge...@apache.org
Subject cvs commit: modperl-2.0/t/response/TestAPR table.pm
Date Mon, 16 Feb 2004 19:58:18 GMT
geoff       2004/02/16 11:58:18

  Modified:    .        Changes
               src/modules/perl modperl_apache_compat.c
               t/response/TestAPR table.pm
  Log:
  copy apr_table_compress logic from later httpd versions in case mod_perl
  is built against 2.0.46, as mod_perl now requires it internally.
  
  Revision  Changes    Path
  1.331     +5 -0      modperl-2.0/Changes
  
  Index: Changes
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/Changes,v
  retrieving revision 1.330
  retrieving revision 1.331
  diff -u -r1.330 -r1.331
  --- Changes	14 Feb 2004 01:38:05 -0000	1.330
  +++ Changes	16 Feb 2004 19:58:18 -0000	1.331
  @@ -12,6 +12,11 @@
   
   =item 1.99_13-dev
   
  +copy apr_table_compress logic from later httpd versions in case mod_perl
  +is built against 2.0.46, as mod_perl now requires it internally.  users
  +should be aware that 2.0.47 may become the oldest supported httpd version 
  +in the near future.  [Geoffrey Young]
  +
   Fix the corruption of the httpd process argv[0], caused by $0
   manipulating [Stas]
   
  
  
  
  1.4       +217 -2    modperl-2.0/src/modules/perl/modperl_apache_compat.c
  
  Index: modperl_apache_compat.c
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_apache_compat.c,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- modperl_apache_compat.c	22 Aug 2003 19:15:09 -0000	1.3
  +++ modperl_apache_compat.c	16 Feb 2004 19:58:18 -0000	1.4
  @@ -10,10 +10,225 @@
      which is major mmn 20020903, minor mmn 4 */
   #if ! AP_MODULE_MAGIC_AT_LEAST(20020903,4)
   
  -/* added in APACHE_2_0_47/APR_0_9_4 */
  +/* added in APACHE_2_0_47/APR_0_9_4 - duplicated here for 2.0.46.
  + * I'd rather not duplicate it, but we use apr_table_compress
  + * in the directive merge routines, so it's either duplicate it
  + * here, recode the compress logic there, or drop 2.0.46 support
  + */
  +
  +#define TABLE_HASH_SIZE 32
  +
  +struct apr_table_t {
  +    apr_array_header_t a;
  +#ifdef MAKE_TABLE_PROFILE
  +    /** Who created the array. */
  +    void *creator;
  +#endif
  +    apr_uint32_t index_initialized;
  +    int index_first[TABLE_HASH_SIZE];
  +    int index_last[TABLE_HASH_SIZE];
  +};
  +
  +static apr_table_entry_t **table_mergesort(apr_pool_t *pool,
  +                                           apr_table_entry_t **values, int n)
  +{
  +    /* Bottom-up mergesort, based on design in Sedgewick's "Algorithms
  +     * in C," chapter 8
  +     */
  +    apr_table_entry_t **values_tmp =
  +        (apr_table_entry_t **)apr_palloc(pool, n * sizeof(apr_table_entry_t*));
  +    int i;
  +    int blocksize;
  +
  +    /* First pass: sort pairs of elements (blocksize=1) */
  +    for (i = 0; i + 1 < n; i += 2) {
  +        if (strcasecmp(values[i]->key, values[i + 1]->key) > 0) {
  +            apr_table_entry_t *swap = values[i];
  +            values[i] = values[i + 1];
  +            values[i + 1] = swap;
  +        }
  +    }
  +
  +    /* Merge successively larger blocks */
  +    blocksize = 2;
  +    while (blocksize < n) {
  +        apr_table_entry_t **dst = values_tmp;
  +        int next_start;
  +        apr_table_entry_t **swap;
  +
  +        /* Merge consecutive pairs blocks of the next blocksize.
  +         * Within a block, elements are in sorted order due to
  +         * the previous iteration.
  +         */
  +        for (next_start = 0; next_start + blocksize < n;
  +             next_start += (blocksize + blocksize)) {
  +
  +            int block1_start = next_start;
  +            int block2_start = block1_start + blocksize;
  +            int block1_end = block2_start;
  +            int block2_end = block2_start + blocksize;
  +            if (block2_end > n) {
  +                /* The last block may be smaller than blocksize */
  +                block2_end = n;
  +            }
  +            for (;;) {
  +
  +                /* Merge the next two blocks:
  +                 * Pick the smaller of the next element from
  +                 * block 1 and the next element from block 2.
  +                 * Once either of the blocks is emptied, copy
  +                 * over all the remaining elements from the
  +                 * other block
  +                 */
  +                if (block1_start == block1_end) {
  +                    for (; block2_start < block2_end; block2_start++) {
  +                        *dst++ = values[block2_start];
  +                    }
  +                    break;
  +                }
  +                else if (block2_start == block2_end) {
  +                    for (; block1_start < block1_end; block1_start++) {
  +                        *dst++ = values[block1_start];
  +                    }
  +                    break;
  +                }
  +                if (strcasecmp(values[block1_start]->key,
  +                               values[block2_start]->key) > 0) {
  +                    *dst++ = values[block2_start++];
  +                }
  +                else {
  +                    *dst++ = values[block1_start++];
  +                }
  +            }
  +        }
  +
  +        /* If n is not a multiple of 2*blocksize, some elements
  +         * will be left over at the end of the array.
  +         */
  +        for (i = dst - values_tmp; i < n; i++) {
  +            values_tmp[i] = values[i];
  +        }
  +
  +        /* The output array of this pass becomes the input
  +         * array of the next pass, and vice versa
  +         */
  +        swap = values_tmp;
  +        values_tmp = values;
  +        values = swap;
  +
  +        blocksize += blocksize;
  +    }
  +
  +    return values;
  +}
   void apr_table_compress(apr_table_t *t, unsigned flags)
   {
  -    modperl_apr_func_not_implemented(apr_table_compress, 2.0.47, 0.9.4);
  +    apr_table_entry_t **sort_array;
  +    apr_table_entry_t **sort_next;
  +    apr_table_entry_t **sort_end;
  +    apr_table_entry_t *table_next;
  +    apr_table_entry_t **last;
  +    int i;
  +    int dups_found;
  +
  +    if (t->a.nelts <= 1) {
  +        return;
  +    }
  +
  +    /* Copy pointers to all the table elements into an
  +     * array and sort to allow for easy detection of
  +     * duplicate keys
  +     */
  +    sort_array = (apr_table_entry_t **)
  +        apr_palloc(t->a.pool, t->a.nelts * sizeof(apr_table_entry_t*));
  +    sort_next = sort_array;
  +    table_next = (apr_table_entry_t *)t->a.elts;
  +    i = t->a.nelts;
  +    do {
  +        *sort_next++ = table_next++;
  +    } while (--i);
  +
  +    /* Note: the merge is done with mergesort instead of quicksort
  +     * because mergesort is a stable sort and runs in n*log(n)
  +     * time regardless of its inputs (quicksort is quadratic in
  +     * the worst case)
  +     */
  +    sort_array = table_mergesort(t->a.pool, sort_array, t->a.nelts);
  +
  +    /* Process any duplicate keys */
  +    dups_found = 0;
  +    sort_next = sort_array;
  +    sort_end = sort_array + t->a.nelts;
  +    last = sort_next++;
  +    while (sort_next < sort_end) {
  +        if (((*sort_next)->key_checksum == (*last)->key_checksum) &&
  +            !strcasecmp((*sort_next)->key, (*last)->key)) {
  +            apr_table_entry_t **dup_last = sort_next + 1;
  +            dups_found = 1;
  +            while ((dup_last < sort_end) &&
  +                   ((*dup_last)->key_checksum == (*last)->key_checksum) &&
  +                   !strcasecmp((*dup_last)->key, (*last)->key)) {
  +                dup_last++;
  +            }
  +            dup_last--; /* Elements from last through dup_last, inclusive,
  +                         * all have the same key
  +                         */
  +            if (flags == APR_OVERLAP_TABLES_MERGE) {
  +                apr_size_t len = 0;
  +                apr_table_entry_t **next = last;
  +                char *new_val;
  +                char *val_dst;
  +                do {
  +                    len += strlen((*next)->val);
  +                    len += 2; /* for ", " or trailing null */
  +                } while (++next <= dup_last);
  +                new_val = (char *)apr_palloc(t->a.pool, len);
  +                val_dst = new_val;
  +                next = last;
  +                for (;;) {
  +                    strcpy(val_dst, (*next)->val);
  +                    val_dst += strlen((*next)->val);
  +                    next++;
  +                    if (next > dup_last) {
  +                        *val_dst = 0;
  +                        break;
  +                    }
  +                    else {
  +                        *val_dst++ = ',';
  +                        *val_dst++ = ' ';
  +                    }
  +                }
  +                (*last)->val = new_val;
  +            }
  +            else { /* overwrite */
  +                (*last)->val = (*dup_last)->val;
  +            }
  +            do {
  +                (*sort_next)->key = NULL;
  +            } while (++sort_next <= dup_last);
  +        }
  +        else {
  +            last = sort_next++;
  +        }
  +    }
  +
  +    /* Shift elements to the left to fill holes left by removing duplicates */
  +    if (dups_found) {
  +        apr_table_entry_t *src = (apr_table_entry_t *)t->a.elts;
  +        apr_table_entry_t *dst = (apr_table_entry_t *)t->a.elts;
  +        apr_table_entry_t *last_elt = src + t->a.nelts;
  +        do {
  +            if (src->key) {
  +                *dst++ = *src;
  +            }
  +        } while (++src < last_elt);
  +        t->a.nelts -= (last_elt - dst);
  +    }
  +
  +    /* XXX mod_perl: remove to avoid more code duplication.
  +     * XXX makes us slower on 2.0.46
  +     */
  +    /* table_reindex(t); */
   }
   
   #endif /* pre-APR_0_9_5 (APACHE_2_0_47) */
  
  
  
  1.13      +10 -16    modperl-2.0/t/response/TestAPR/table.pm
  
  Index: table.pm
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/t/response/TestAPR/table.pm,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- table.pm	25 Nov 2003 20:31:29 -0000	1.12
  +++ table.pm	16 Feb 2004 19:58:18 -0000	1.13
  @@ -14,13 +14,10 @@
   my $filter_count;
   my $TABLE_SIZE = 20;
   
  -use constant HAVE_APACHE_2_0_47 => have_min_apache_version('2.0.47');
  -
   sub handler {
       my $r = shift;
   
  -    my $tests = 21;
  -    $tests += 2 if HAVE_APACHE_2_0_47;
  +    my $tests = 23;
   
       plan $r, tests => $tests;
   
  @@ -133,18 +130,15 @@
       ok @foo == 3;
       ok $bar[0] eq 'beer';
   
  -    # BACK_COMPAT_MARKER: make back compat issues easy to find :)
  -    if (HAVE_APACHE_2_0_47) {
  -        $overlay->compress(APR::OVERLAP_TABLES_MERGE);
  -
  -        # $add first, then $base
  -        ok t_cmp($overlay->get('foo'),
  -                 'three, one, two',
  -                 "\$overlay->compress");
  -        ok t_cmp($overlay->get('bar'),
  -                 'beer',
  -                 "\$overlay->compress");
  -    }
  +    $overlay->compress(APR::OVERLAP_TABLES_MERGE);
  +
  +    # $add first, then $base
  +    ok t_cmp($overlay->get('foo'),
  +             'three, one, two',
  +             "\$overlay->compress");
  +    ok t_cmp($overlay->get('bar'),
  +             'beer',
  +             "\$overlay->compress");
   
       Apache::OK;
   }
  
  
  

Mime
View raw message