Author: gozer Date: Fri Mar 17 17:32:33 2006 New Revision: 386784 URL: http://svn.apache.org/viewcvs?rev=386784&view=rev Log: Added $r->connection->pnotes, identical to $r->pnotes, but for the entire lifetime of the connection
Added: perl/modperl/trunk/t/modperl/pnotes.t perl/modperl/trunk/xs/Apache2/ConnectionUtil/ perl/modperl/trunk/xs/Apache2/ConnectionUtil/Apache2__ConnectionUtil.h Modified: perl/modperl/trunk/Changes perl/modperl/trunk/src/modules/perl/modperl_config.c perl/modperl/trunk/src/modules/perl/modperl_config.h perl/modperl/trunk/src/modules/perl/modperl_types.h perl/modperl/trunk/src/modules/perl/modperl_util.c perl/modperl/trunk/src/modules/perl/modperl_util.h perl/modperl/trunk/t/response/TestModperl/pnotes.pm perl/modperl/trunk/xs/Apache2/RequestUtil/Apache2__RequestUtil.h perl/modperl/trunk/xs/maps/modperl_functions.map perl/modperl/trunk/xs/tables/current/ModPerl/FunctionTable.pm Modified: perl/modperl/trunk/Changes URL: http://svn.apache.org/viewcvs/perl/modperl/trunk/Changes?rev=386784&r1=386783&r2=386784&view=diff ============================================================================== --- perl/modperl/trunk/Changes (original) +++ perl/modperl/trunk/Changes Fri Mar 17 17:32:33 2006 @@ -12,6 +12,10 @@ =item 2.0.3-dev +Added $r->connection->pnotes, identical to $r->pnotes, but +for the entire lifetime of the connection +[Geoffrey Young, Gozer] + Fixed problems with add_config() and thread-safety: [Gozer] - $s->add_config is not allowed anymore after server startup - $r->add_config can only affect configuration for the current Modified: perl/modperl/trunk/src/modules/perl/modperl_config.c URL: http://svn.apache.org/viewcvs/perl/modperl/trunk/src/modules/perl/modperl_config.c?rev=386784&r1=386783&r2=386784&view=diff ============================================================================== --- perl/modperl/trunk/src/modules/perl/modperl_config.c (original) +++ perl/modperl/trunk/src/modules/perl/modperl_config.c Fri Mar 17 17:32:33 2006 @@ -147,6 +147,16 @@ return rcfg; } +modperl_config_con_t *modperl_config_con_new(conn_rec *c) +{ + modperl_config_con_t *ccfg = + (modperl_config_con_t *)apr_pcalloc(c->pool, sizeof(*ccfg)); + + MP_TRACE_d(MP_FUNC, "0x%lx\n", (unsigned long)ccfg); + + return ccfg; +} + modperl_config_srv_t *modperl_config_srv_new(apr_pool_t *p, server_rec *s) { modperl_config_srv_t *scfg = (modperl_config_srv_t *) Modified: perl/modperl/trunk/src/modules/perl/modperl_config.h URL: http://svn.apache.org/viewcvs/perl/modperl/trunk/src/modules/perl/modperl_config.h?rev=386784&r1=386783&r2=386784&view=diff ============================================================================== --- perl/modperl/trunk/src/modules/perl/modperl_config.h (original) +++ perl/modperl/trunk/src/modules/perl/modperl_config.h Fri Mar 17 17:32:33 2006 @@ -26,6 +26,8 @@ modperl_config_req_t *modperl_config_req_new(request_rec *r); +modperl_config_con_t *modperl_config_con_new(conn_rec *c); + void *modperl_config_srv_create(apr_pool_t *p, server_rec *s); void *modperl_config_srv_merge(apr_pool_t *p, void *basev, void *addv); @@ -78,6 +80,19 @@ #define MP_dRCFG \ modperl_config_req_t *rcfg = modperl_config_req_get(r) +#define modperl_config_con_init(c, ccfg) \ + if (!ccfg) { \ + ccfg = modperl_config_con_new(c); \ + modperl_set_module_config(c->conn_config, ccfg); \ + } + +#define modperl_config_con_get(c) \ + (c ? (modperl_config_con_t *) \ + modperl_get_module_config(c->conn_config) : NULL) + +#define MP_dCCFG \ + modperl_config_con_t *ccfg = modperl_config_con_get(c) + #define modperl_config_dir_get(r) \ (r ? (modperl_config_dir_t *) \ modperl_get_module_config(r->per_dir_config) : NULL) Modified: perl/modperl/trunk/src/modules/perl/modperl_types.h URL: http://svn.apache.org/viewcvs/perl/modperl/trunk/src/modules/perl/modperl_types.h?rev=386784&r1=386783&r2=386784&view=diff ============================================================================== --- perl/modperl/trunk/src/modules/perl/modperl_types.h (original) +++ perl/modperl/trunk/src/modules/perl/modperl_types.h Fri Mar 17 17:32:33 2006 @@ -258,7 +258,7 @@ } modperl_config_req_t; typedef struct { - MpAV *handlers_connection[MP_HANDLER_NUM_CONNECTION]; + HV *pnotes; } modperl_config_con_t; typedef struct { Modified: perl/modperl/trunk/src/modules/perl/modperl_util.c URL: http://svn.apache.org/viewcvs/perl/modperl/trunk/src/modules/perl/modperl_util.c?rev=386784&r1=386783&r2=386784&view=diff ============================================================================== --- perl/modperl/trunk/src/modules/perl/modperl_util.c (original) +++ perl/modperl/trunk/src/modules/perl/modperl_util.c Fri Mar 17 17:32:33 2006 @@ -829,11 +829,59 @@ return data ? *(int *)data : 0; } -SV *modperl_pnotes(pTHX_ HV **pnotes, SV *key, SV *val, request_rec *r) { +#ifdef USE_ITHREADS +typedef struct { + HV **pnotes; + PerlInterpreter *perl; +} modperl_cleanup_pnotes_data_t; +#endif + +static MP_INLINE +apr_status_t modperl_cleanup_pnotes(void *data) { + HV **pnotes = data; + + if (*pnotes) { +#ifdef USE_ITHREADS + modperl_cleanup_pnotes_data_t *cleanup_data = data; + dTHXa(cleanup_data->perl); + pnotes = cleanup_data->pnotes; +#else + pnotes = data; +#endif + SvREFCNT_dec(*pnotes); + *pnotes = Nullhv; + } + + return APR_SUCCESS; +} + +SV *modperl_pnotes(pTHX_ HV **pnotes, SV *key, SV *val, + request_rec *r, conn_rec *c) { SV *retval = Nullsv; if (!*pnotes) { *pnotes = newHV(); + + /* XXX: It would be nice to be able to do this with r->pnotes, but + * it's currently impossible, as modperl_config.c:modperl_config_request_cleanup() + * is responsible for running the CleanupHandlers, and it's cleanup callback is + * registered very early. If we register our cleanup here, we'll be running + * *before* the CleanupHandlers, and they might still want to use pnotes... + */ + if (c && !r) { + apr_pool_t *pool = r ? r->pool : c->pool; +#ifdef USE_ITHREADS + modperl_cleanup_pnotes_data_t *cleanup_data = + apr_palloc(pool, sizeof(*cleanup_data)); + cleanup_data->pnotes = pnotes; + cleanup_data->perl = aTHX; +#else + void *cleanup_data = pnotes; +#endif + apr_pool_cleanup_register(pool, cleanup_data, + modperl_cleanup_pnotes, + apr_pool_cleanup_null); + } } if (key) { Modified: perl/modperl/trunk/src/modules/perl/modperl_util.h URL: http://svn.apache.org/viewcvs/perl/modperl/trunk/src/modules/perl/modperl_util.h?rev=386784&r1=386783&r2=386784&view=diff ============================================================================== --- perl/modperl/trunk/src/modules/perl/modperl_util.h (original) +++ perl/modperl/trunk/src/modules/perl/modperl_util.h Fri Mar 17 17:32:33 2006 @@ -145,6 +145,7 @@ void modperl_restart_count_inc(server_rec *base_server); int modperl_restart_count(void); -SV *modperl_pnotes(pTHX_ HV **pnotes, SV *key, SV *val, request_rec *r); +SV *modperl_pnotes(pTHX_ HV **pnotes, SV *key, SV *val, + request_rec *r, conn_rec *c); #endif /* MODPERL_UTIL_H */ Added: perl/modperl/trunk/t/modperl/pnotes.t URL: http://svn.apache.org/viewcvs/perl/modperl/trunk/t/modperl/pnotes.t?rev=386784&view=auto ============================================================================== --- perl/modperl/trunk/t/modperl/pnotes.t (added) +++ perl/modperl/trunk/t/modperl/pnotes.t Fri Mar 17 17:32:33 2006 @@ -0,0 +1,27 @@ +use strict; +use warnings FATAL => 'all'; + +use Apache::TestRequest qw(GET_BODY_ASSERT); +use Apache::Test; +use Apache::TestUtil; + +my $module = 'TestModperl::pnotes'; +my $url = Apache::TestRequest::module2url($module); + +t_debug("connecting to $url"); + +plan tests => (22 * 3); + +# first with keepalives +Apache::TestRequest::user_agent(reset => 1, keep_alive => 1); +t_debug("issuing first request"); +print GET_BODY_ASSERT "$url?1"; + +# now close the connection +t_debug("issuing second request"); +print GET_BODY_ASSERT "$url?2", Connection => 'close'; + +# finally, check for a cleared $c->pnotes +t_debug("issuing final request"); +print GET_BODY_ASSERT "$url?3"; + Modified: perl/modperl/trunk/t/response/TestModperl/pnotes.pm URL: http://svn.apache.org/viewcvs/perl/modperl/trunk/t/response/TestModperl/pnotes.pm?rev=386784&r1=386783&r2=386784&view=diff ============================================================================== --- perl/modperl/trunk/t/response/TestModperl/pnotes.pm (original) +++ perl/modperl/trunk/t/response/TestModperl/pnotes.pm Fri Mar 17 17:32:33 2006 @@ -4,6 +4,7 @@ use warnings FATAL => 'all'; use Apache2::RequestUtil (); +use Apache2::ConnectionUtil (); use Apache::Test; use Apache::TestUtil; @@ -11,38 +12,89 @@ use Apache2::Const -compile => 'OK'; sub handler { - my $r = shift; - - plan $r, tests => 9; - ok $r->pnotes; + my $r = shift; - ok t_cmp($r->pnotes('pnotes_foo', 'pnotes_bar'), - 'pnotes_bar', - q{$r->pnotes(key,val)}); - - ok t_cmp($r->pnotes('pnotes_foo'), - 'pnotes_bar', - q{$r->pnotes(key)}); - - ok t_cmp(ref($r->pnotes), 'HASH', q{ref($r->pnotes)}); - - ok t_cmp($r->pnotes()->{'pnotes_foo'}, 'pnotes_bar', - q{$r->pnotes()->{}}); - - # unset the entry (but the entry remains with undef value) - $r->pnotes('pnotes_foo', undef); - ok t_cmp($r->pnotes('pnotes_foo'), undef, - q{unset entry contents}); - my $exists = exists $r->pnotes->{'pnotes_foo'}; - $exists = 1 if $] < 5.008001; # changed in perl 5.8.1 - ok $exists; - - # now delete completely (possible only via the hash inteface) - delete $r->pnotes()->{'pnotes_foo'}; - ok t_cmp($r->pnotes('pnotes_foo'), undef, - q{deleted entry contents}); - ok !exists $r->pnotes->{'pnotes_foo'}; + # make it ok to call ok() here while plan()ing elsewhere + Apache::Test::init_test_pm($r); + + Test::_reset_globals() if Test->can('_reset_globals'); + $Test::ntest = 1 + (22 * ($r->args - 1)); + $Test::planned = 22; + + my $c = $r->connection; + + # we call this handler 3 times. + # $r->pnotes('request') should be unset each time + # $c->pnotes('connection') should be unset the first + # time but set the second time due to the keepalive + # request. the second request then cleans up after + # itself, leaving $c->pnotes again unset at the + # start of the third request + if ($r->args == 2) { + ok t_cmp($c->pnotes('connection'), + 'CSET', + '$c->pnotes() persists across keepalive requests'); + } + else { + t_debug('testing $c->pnotes is empty'); + ok (! $c->pnotes('connection')); + } + + # $r->pnotes should be reset each time + t_debug('testing $r->pnotes is empty'); + ok (! $r->pnotes('request')); + + foreach my $map ({type => 'r', object => $r}, + {type => 'c', object => $c}) { + + my $type = $map->{type}; + + my $o = $map->{object}; + + t_debug("testing $type->pnotes call"); + ok $o->pnotes; + + ok t_cmp($o->pnotes('pnotes_foo', 'pnotes_bar'), + 'pnotes_bar', + "$type->pnotes(key,val)"); + + ok t_cmp($o->pnotes('pnotes_foo'), + 'pnotes_bar', + "$type->pnotes(key)"); + + ok t_cmp(ref($o->pnotes), 'HASH', "ref($type->pnotes)"); + + ok t_cmp($o->pnotes()->{'pnotes_foo'}, 'pnotes_bar', + "$type->pnotes()->{}"); + + # unset the entry (but the entry remains with undef value) + $o->pnotes('pnotes_foo', undef); + ok t_cmp($o->pnotes('pnotes_foo'), undef, + "unset $type contents"); + + my $exists = exists $o->pnotes->{'pnotes_foo'}; + $exists = 1 if $] < 5.008001; # changed in perl 5.8.1 + ok $exists; + + # now delete completely (possible only via the hash inteface) + delete $o->pnotes()->{'pnotes_foo'}; + ok t_cmp($o->pnotes('pnotes_foo'), undef, + "deleted $type contents"); + ok !exists $o->pnotes->{'pnotes_foo'}; + } + + # set pnotes so we can test unset on later connections + $r->pnotes(request => 'RSET'); + $c->pnotes(connection => 'CSET'); + + ok t_cmp($r->pnotes('request'), + 'RSET', + '$r->pnotes() set'); + + ok t_cmp($c->pnotes('connection'), + 'CSET', + '$c->pnotes() set'); Apache2::Const::OK; } Added: perl/modperl/trunk/xs/Apache2/ConnectionUtil/Apache2__ConnectionUtil.h URL: http://svn.apache.org/viewcvs/perl/modperl/trunk/xs/Apache2/ConnectionUtil/Apache2__ConnectionUtil.h?rev=386784&view=auto ============================================================================== --- perl/modperl/trunk/xs/Apache2/ConnectionUtil/Apache2__ConnectionUtil.h (added) +++ perl/modperl/trunk/xs/Apache2/ConnectionUtil/Apache2__ConnectionUtil.h Fri Mar 17 17:32:33 2006 @@ -0,0 +1,28 @@ +/* Copyright 2001-2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +static MP_INLINE +SV *mpxs_Apache2__Connection_pnotes(pTHX_ conn_rec *c, SV *key, SV *val) +{ + MP_dCCFG; + + modperl_config_con_init(c, ccfg); + + if (!ccfg) { + return &PL_sv_undef; + } + + return modperl_pnotes(aTHX_ &ccfg->pnotes, key, val, NULL, c); +} Modified: perl/modperl/trunk/xs/Apache2/RequestUtil/Apache2__RequestUtil.h URL: http://svn.apache.org/viewcvs/perl/modperl/trunk/xs/Apache2/RequestUtil/Apache2__RequestUtil.h?rev=386784&r1=386783&r2=386784&view=diff ============================================================================== --- perl/modperl/trunk/xs/Apache2/RequestUtil/Apache2__RequestUtil.h (original) +++ perl/modperl/trunk/xs/Apache2/RequestUtil/Apache2__RequestUtil.h Fri Mar 17 17:32:33 2006 @@ -217,7 +217,7 @@ return &PL_sv_undef; } - return modperl_pnotes(aTHX_ &rcfg->pnotes, key, val, r); + return modperl_pnotes(aTHX_ &rcfg->pnotes, key, val, r, NULL); } #define mpxs_Apache2__RequestRec_dir_config(r, key, sv_val) \ Modified: perl/modperl/trunk/xs/maps/modperl_functions.map URL: http://svn.apache.org/viewcvs/perl/modperl/trunk/xs/maps/modperl_functions.map?rev=386784&r1=386783&r2=386784&view=diff ============================================================================== --- perl/modperl/trunk/xs/maps/modperl_functions.map (original) +++ perl/modperl/trunk/xs/maps/modperl_functions.map Fri Mar 17 17:32:33 2006 @@ -93,6 +93,9 @@ MODULE=Apache2::Connection mpxs_Apache2__Connection_client_socket | | c, s=NULL +MODULE=Apache2::ConnectionUtil PACKAGE=guess + mpxs_Apache2__Connection_pnotes | | c, key=Nullsv, val=Nullsv + MODULE=Apache2::Filter modperl_filter_attributes | MPXS_ | ... | MODIFY_CODE_ATTRIBUTES Modified: perl/modperl/trunk/xs/tables/current/ModPerl/FunctionTable.pm URL: http://svn.apache.org/viewcvs/perl/modperl/trunk/xs/tables/current/ModPerl/FunctionTable.pm?rev=386784&r1=386783&r2=386784&view=diff ============================================================================== --- perl/modperl/trunk/xs/tables/current/ModPerl/FunctionTable.pm (original) +++ perl/modperl/trunk/xs/tables/current/ModPerl/FunctionTable.pm Fri Mar 17 17:32:33 2006 @@ -1493,6 +1493,16 @@ ] }, { + 'return_type' => 'modperl_config_con_t *', + 'name' => 'modperl_config_con_new', + 'args' => [ + { + 'type' => 'conn_rec *', + 'name' => 'c' + } + ] + }, + { 'return_type' => 'apr_status_t', 'name' => 'modperl_config_request_cleanup', 'args' => [ @@ -6229,6 +6239,28 @@ { 'type' => 'ap_conf_vector_t *', 'name' => 'dir_config' + } + ] + }, + { + 'return_type' => 'SV *', + 'name' => 'mpxs_Apache2__Connection_pnotes', + 'args' => [ + { + 'type' => 'PerlInterpreter *', + 'name' => 'my_perl' + }, + { + 'type' => 'conn_rec *', + 'name' => 'c' + }, + { + 'type' => 'SV *', + 'name' => 'key' + }, + { + 'type' => 'SV *', + 'name' => 'val' } ] },