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'
}
]
},