geoff 2004/01/27 08:34:37
Modified: t/response/TestAPR flatten.pm xs/APR/Brigade APR__Brigade.h xs/maps apr_functions.map xs/tables/current/ModPerl FunctionTable.pm Log: rework apr_brigade_flatten and apr_brigade_pflatten into a single APR::Brigade::flatten() Revision Changes Path 1.2 +62 -38 modperl-2.0/t/response/TestAPR/flatten.pm Index: flatten.pm =================================================================== RCS file: /home/cvs/modperl-2.0/t/response/TestAPR/flatten.pm,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- flatten.pm 23 Jan 2004 15:26:55 -0000 1.1 +++ flatten.pm 27 Jan 2004 16:34:36 -0000 1.2 @@ -16,11 +16,13 @@ my $r = shift; - plan $r, tests => 9; + plan $r, tests => 14; # first, create a brigade - my $bb = APR::Brigade->new($r->pool, - $r->connection->bucket_alloc); + my $pool = $r->pool; + my $ba = $r->connection->bucket_alloc; + + my $bb = APR::Brigade->new($pool, $ba); # now, let's put several buckets in it for (1 .. 10) { @@ -34,19 +36,17 @@ $bb->length, 'APR::Brigade::length()'); - # slurp up the entire brigade - # this is somewhat wasteful, since we're simulating a user - # 'guessing' at how much data there is to slurp - { - my $rc = $bb->flatten(my $data, my $length = 300000); - - ok t_cmp(APR::SUCCESS, - $rc, - 'APR::Brigade::flatten() return value'); + # syntax: always require a pool + eval { $bb->flatten() }; - ok t_cmp(200000, - $length, - 'APR::Brigade::flatten() length population'); + ok t_cmp(qr/Usage: APR::Brigade::flatten/, + $@, + 'APR::Brigade::flatten() requires a pool'); + + # flatten($pool) will slurp up the entire brigade + # equivalent to calling apr_brigade_pflatten + { + my $data = $bb->flatten($pool); ok t_cmp(200000, length($data), @@ -58,44 +58,68 @@ ok ($data !~ m/[^x]/); } - # test that other length variants - such as constants and - # subroutine returns - don't segfault + # syntax: flatten($p, 0) is equivalent to flatten($p) { - my $rc = $bb->flatten(my $data, 300000); + my $data = $bb->flatten($pool, 0); + + ok t_cmp(200000, + length($data), + 'APR::Brigade::flatten() returned all the data'); - ok t_cmp(APR::SUCCESS, - $rc, - 'APR::Brigade::flatten() return value'); + t_debug("APR::Brigade::flatten() data all 'x' characters"); + ok ($data !~ m/[^x]/); } - # this is probably the best example of using flatten() to - # get the entire brigade - using $bb->length to determine - # the full size of the brigade. - # probably still inefficient, though... + + # flatten($pool, $length) will return the first $length bytes + # equivalent to calling apr_brigade_flatten { - my $rc = $bb->flatten(my $data, $bb->length); + # small + my $data = $bb->flatten($pool, 30); + + ok t_cmp(30, + length($data), + 'APR::Brigade::flatten() returned all the data'); - ok t_cmp(APR::SUCCESS, - $rc, - 'APR::Brigade::flatten() return value'); + t_debug("APR::Brigade::flatten() data all 'x' characters"); + ok ($data !~ m/[^x]/); } - # this is the most proper use of flatten() - retrieving - # only a chunk of a brigade. most examples in httpd core - # use flatten() to grab the first 30 bytes or so { - my $rc = $bb->flatten(my $data, 100000); + # large + my $data = $bb->flatten($pool, 190000); - ok t_cmp(APR::SUCCESS, - $rc, - 'APR::Brigade::flatten() return value'); + ok t_cmp(190000, + length($data), + 'APR::Brigade::flatten() returned all the data'); + + t_debug("APR::Brigade::flatten() data all 'x' characters"); + ok ($data !~ m/[^x]/); + } + + { + # more than enough + my $data = $bb->flatten($pool, 300000); - ok t_cmp(100000, + ok t_cmp(200000, length($data), 'APR::Brigade::flatten() returned all the data'); + + t_debug("APR::Brigade::flatten() data all 'x' characters"); + ok ($data !~ m/[^x]/); } - # pflatten() examples to come... + # fetch from a brigade with no data in it + { + my $data = APR::Brigade->new($pool, $ba)->flatten($pool); + + t_debug('an empty brigade returns a defined value'); + ok (defined $data); + + ok t_cmp(0, + length($data), + 'an empty brigade returns data of 0 length'); + } Apache::OK; } 1.6 +43 -9 modperl-2.0/xs/APR/Brigade/APR__Brigade.h Index: APR__Brigade.h =================================================================== RCS file: /home/cvs/modperl-2.0/xs/APR/Brigade/APR__Brigade.h,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- APR__Brigade.h 23 Jan 2004 15:26:55 -0000 1.5 +++ APR__Brigade.h 27 Jan 2004 16:34:36 -0000 1.6 @@ -87,19 +87,53 @@ } static MP_INLINE -apr_status_t mpxs_apr_brigade_flatten(pTHX_ apr_bucket_brigade *bb, - SV *sv_buf, SV *sv_len) +SV *mpxs_APR__Brigade_flatten(pTHX_ apr_bucket_brigade *bb, + apr_pool_t *pool, SV *sv_len) { + + /* XXX we're deviating from the API here to try and make + * the API more Perlish - nobody likes the idea of two + * "in/out" arguments. and we generally don't ever need + * the length anyway... + */ + apr_status_t status; - apr_size_t len = mp_xs_sv2_apr_size_t(sv_len); + char *buffer; + apr_size_t length; + + if (SvTRUE(sv_len)) { + /* APR::Brigade->flatten($p, $length); + * use apr_brigade_flatten to get the first $length bytes + * + * note that $length must be non-zero to get here + */ + + length = mp_xs_sv2_apr_size_t(sv_len); + + /* since we always require a pool, we can allocate from it */ + buffer = apr_pcalloc(pool, length); - mpxs_sv_grow(sv_buf, len); - status = apr_brigade_flatten(bb, SvPVX(sv_buf), &len); - mpxs_sv_cur_set(sv_buf, len); + status = apr_brigade_flatten(bb, buffer, &length); + + } + else { + /* APR::Brigade->flatten($p); + * use apr_brigade_pflatten to slurp the entire brigade + * + * note that it doesn't matter what we pass in for length + */ + + status = apr_brigade_pflatten(bb, &buffer, &length, pool); + + } - if (!SvREADONLY(sv_len)) { - sv_setiv(sv_len, len); + if (status != APR_SUCCESS) { + /* XXX croak? + * note that reading from an empty brigade will return + * an empty string, not undef, so there is a difference + */ + return &PL_sv_undef; } - return status; + return newSVpvn(buffer, length); } 1.67 +3 -2 modperl-2.0/xs/maps/apr_functions.map Index: apr_functions.map =================================================================== RCS file: /home/cvs/modperl-2.0/xs/maps/apr_functions.map,v retrieving revision 1.66 retrieving revision 1.67 diff -u -r1.66 -r1.67 --- apr_functions.map 23 Jan 2004 15:26:55 -0000 1.66 +++ apr_functions.map 27 Jan 2004 16:34:36 -0000 1.67 @@ -86,8 +86,8 @@ !apr_brigade_puts -apr_brigade_putc !apr_brigade_cleanup - apr_brigade_flatten | mpxs_ | bb, SV *:sv_buf, SV *:sv_len -?apr_brigade_pflatten +~apr_brigade_flatten +~apr_brigade_pflatten ?apr_brigade_split_line mpxs_APR__Brigade_first #APR_BRIGADE_FIRST mpxs_APR__Brigade_last #APR_BRIGADE_LAST @@ -98,6 +98,7 @@ mpxs_APR__Brigade_concat #APR_BRIGADE_CONCAT mpxs_APR__Brigade_empty #APR_BRIGADE_EMPTY mpxs_APR__Brigade_length | | bb, read_all=1 + mpxs_APR__Brigade_flatten | | bb, pool, sv_len=0 MODULE=APR::Bucket mpxs_APR__Bucket_is_flush #APR_BUCKET_IS_FLUSH 1.140 +4 -4 modperl-2.0/xs/tables/current/ModPerl/FunctionTable.pm Index: FunctionTable.pm =================================================================== RCS file: /home/cvs/modperl-2.0/xs/tables/current/ModPerl/FunctionTable.pm,v retrieving revision 1.139 retrieving revision 1.140 diff -u -r1.139 -r1.140 --- FunctionTable.pm 23 Jan 2004 15:26:56 -0000 1.139 +++ FunctionTable.pm 27 Jan 2004 16:34:36 -0000 1.140 @@ -6462,8 +6462,8 @@ ] }, { - 'return_type' => 'apr_status_t', - 'name' => 'mpxs_apr_brigade_flatten', + 'return_type' => 'SV *', + 'name' => 'mpxs_APR__Brigade_flatten', 'args' => [ { 'type' => 'PerlInterpreter *', @@ -6474,8 +6474,8 @@ 'name' => 'bb' }, { - 'type' => 'SV *', - 'name' => 'sv_buf' + 'type' => 'apr_pool_t *', + 'name' => 'pool' }, { 'type' => 'SV *',