geoff 2004/09/20 11:14:48
Modified: . Changes
src/modules/perl mod_perl.h modperl_cmd.c modperl_config.c
modperl_types.h
t/response/TestModperl merge.pm
Log:
get PerlSetVar and PerlAddVar multi-level merges to (finally) work
properly.
Submitted by: [EMAIL PROTECTED]
Reviewed by: geoff
Revision Changes Path
1.489 +3 -0 modperl-2.0/Changes
Index: Changes
===================================================================
RCS file: /home/cvs/modperl-2.0/Changes,v
retrieving revision 1.488
retrieving revision 1.489
diff -u -r1.488 -r1.489
--- Changes 18 Sep 2004 22:17:59 -0000 1.488
+++ Changes 20 Sep 2004 18:14:47 -0000 1.489
@@ -12,6 +12,9 @@
=item 1.99_17-dev
+get PerlSetVar and PerlAddVar multi-level merges to (finally) work
+properly. [Rici Lake <rici ricilake.net>]
+
MP_AP_BUILD configure option removed. Now implicit when MP_USE_STATIC
is specified [Gozer]
1.70 +4 -3 modperl-2.0/src/modules/perl/mod_perl.h
Index: mod_perl.h
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/mod_perl.h,v
retrieving revision 1.69
retrieving revision 1.70
diff -u -r1.69 -r1.70
--- mod_perl.h 18 Sep 2004 04:33:34 -0000 1.69
+++ mod_perl.h 20 Sep 2004 18:14:47 -0000 1.70
@@ -130,9 +130,10 @@
#define MgTypeExt(mg) (mg->mg_type == '~')
-typedef void MP_FUNC_T(modperl_table_modify_t) (apr_table_t *,
- const char *,
- const char *);
+typedef void MP_FUNC_T(modperl_var_modify_t) (apr_table_t *,
+ apr_table_t *,
+ const char *,
+ const char *);
/* we need to hook a few internal things before APR_HOOK_REALLY_FIRST */
#define MODPERL_HOOK_REALLY_REALLY_FIRST (-20)
1.66 +29 -38 modperl-2.0/src/modules/perl/modperl_cmd.c
Index: modperl_cmd.c
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_cmd.c,v
retrieving revision 1.65
retrieving revision 1.66
diff -u -r1.65 -r1.66
--- modperl_cmd.c 9 Sep 2004 22:16:37 -0000 1.65
+++ modperl_cmd.c 20 Sep 2004 18:14:48 -0000 1.66
@@ -266,64 +266,55 @@
}
}
-static MP_CMD_SRV_DECLARE2(handle_vars)
+static void modperl_cmd_addvar_func(apr_table_t *configvars,
+ apr_table_t *setvars,
+ const char *key, const char *val)
{
- MP_dSCFG(parms->server);
- modperl_config_dir_t *dcfg = (modperl_config_dir_t *)mconfig;
- const char *name = parms->cmd->name;
+ apr_table_addn(configvars, key, val);
+}
- /* PerlSetVar and PerlAddVar logic. here's the deal...
- *
- * cfg->configvars holds the final PerlSetVar/PerlAddVar configuration
- * for a given server or directory. however, getting to that point
- * is kind of tricky, due to the add-style nature of PerlAddVar.
- *
- * the solution is to use cfg->setvars to hold PerlSetVar entries
- * and cfg->addvars to hold PerlAddVar entries, each serving as a
- * placeholder for when we need to know what's what in the merge routines.
- *
- * however, for the initial pass, apr_table_setn and apr_table_addn
- * will properly build the configvars table, which will be visible to
- * startup scripts trying to access per-server configurations.
- *
- * the end result is that we need to populate all three tables in order
- * to keep things straight later on see merge_table_config_vars in
- * modperl_config.c
- */
- modperl_table_modify_t func =
- strEQ(name, "PerlSetVar") ? apr_table_setn : apr_table_addn;
+/* Conceptually, setvar is { unsetvar; addvar; } */
- apr_table_t *table =
- strEQ(name, "PerlSetVar") ? dcfg->setvars : dcfg->addvars;
+static void modperl_cmd_setvar_func(apr_table_t *configvars,
+ apr_table_t *setvars,
+ const char * key, const char *val)
+{
+ apr_table_setn(setvars, key, val);
+ apr_table_setn(configvars, key, val);
+}
- func(table, arg1, arg2);
- func(dcfg->configvars, arg1, arg2);
+static const char *modperl_cmd_modvar(modperl_var_modify_t varfunc,
+ cmd_parms *parms,
+ modperl_config_dir_t *dcfg,
+ const char *arg1, const char *arg2)
+{
+ varfunc(dcfg->configvars, dcfg->setvars, arg1, arg2);
MP_TRACE_d(MP_FUNC, "%s DIR: arg1 = %s, arg2 = %s\n",
- name, arg1, arg2);
+ parms->cmd->name, arg1, arg2);
/* make available via Apache->server->dir_config */
if (!parms->path) {
- table = strEQ(name, "PerlSetVar") ? scfg->setvars : scfg->addvars;
-
- func(table, arg1, arg2);
- func(scfg->configvars, arg1, arg2);
+ MP_dSCFG(parms->server);
+ varfunc(scfg->configvars, scfg->setvars, arg1, arg2);
MP_TRACE_d(MP_FUNC, "%s SRV: arg1 = %s, arg2 = %s\n",
- name, arg1, arg2);
+ parms->cmd->name, arg1, arg2);
}
return NULL;
}
-MP_CMD_SRV_DECLARE2(set_var)
+MP_CMD_SRV_DECLARE2(add_var)
{
- return modperl_cmd_handle_vars(parms, mconfig, arg1, arg2);
+ modperl_config_dir_t *dcfg = (modperl_config_dir_t *)mconfig;
+ return modperl_cmd_modvar(modperl_cmd_addvar_func, parms, dcfg, arg1, arg2);
}
-MP_CMD_SRV_DECLARE2(add_var)
+MP_CMD_SRV_DECLARE2(set_var)
{
- return modperl_cmd_handle_vars(parms, mconfig, arg1, arg2);
+ modperl_config_dir_t *dcfg = (modperl_config_dir_t *)mconfig;
+ return modperl_cmd_modvar(modperl_cmd_setvar_func, parms, dcfg, arg1, arg2);
}
MP_CMD_SRV_DECLARE2(set_env)
1.83 +25 -63 modperl-2.0/src/modules/perl/modperl_config.c
Index: modperl_config.c
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_config.c,v
retrieving revision 1.82
retrieving revision 1.83
diff -u -r1.82 -r1.83
--- modperl_config.c 18 Sep 2004 04:33:34 -0000 1.82
+++ modperl_config.c 20 Sep 2004 18:14:48 -0000 1.83
@@ -43,6 +43,11 @@
* note that this is equivalent to apr_table_overlap except a new
* table is generated, which is required (otherwise we would clobber
* the existing parent or child configurations)
+ *
+ * note that this is *not* equivalent to apr_table_overlap, although
+ * I think it should be, because apr_table_overlap seems to clear
+ * its first argument when the tables have different pools. I think
+ * this is wrong -- rici
*/
apr_table_t *merge = apr_table_overlay(p, base, add);
@@ -59,54 +64,29 @@
#define merge_table_overlap_item(item) \
mrg->item = modperl_table_overlap(p, base->item, add->item)
-static apr_table_t *merge_table_config_vars(apr_pool_t *p,
- apr_table_t *configvars,
- apr_table_t *set,
- apr_table_t *add)
+static apr_table_t *merge_config_add_vars(apr_pool_t *p,
+ const apr_table_t *base,
+ const apr_table_t *unset,
+ const apr_table_t *add)
{
- apr_table_t *base = apr_table_copy(p, configvars);
- apr_table_t *merged_config_vars;
+ apr_table_t *temp = apr_table_copy(p, base);
const apr_array_header_t *arr;
apr_table_entry_t *entries;
int i;
- /* configvars already contains a properly merged PerlSetVar/PerlAddVar
- * configuration for the base (parent), so all we need to do is merge
- * the add (child) configuration into it properly.
- *
- * any PerlSetVar settings in the add (child) config need to reset
- * existing entries in the base (parent) config, or generate a
- * new entry where none existed previously. PerlAddVar settings
- * are merged into that.
- *
- * unfortunately, there is no set of apr functions to do this for us -
- * apr_compress_table would be ok, except it always merges mulit-valued
- * keys into one, regardless of the APR_OVERLAP_TABLES flag. that is,
- * regardless of whether newer entries are set or merged into existing
- * entries, the entire table is _always_ compressed. this is no good -
- * we need separate entries for existing keys, not a single (compressed)
- * entry.
- *
- * fortunately, the logic here is simple. first, (re)set the base (parent)
- * table where a PerlSetVar entry exists in the add (child) configuration.
- * then, just overlay the PerlAddVar configuration into it.
- */
-
- arr = apr_table_elts(set);
+ /* for each key in unset do apr_table_unset(temp, key); */
+ arr = apr_table_elts(unset);
entries = (apr_table_entry_t *)arr->elts;
/* hopefully this is faster than using apr_table_do */
for (i = 0; i < arr->nelts; i++) {
- apr_table_setn(base, entries[i].key, entries[i].val);
+ if (entries[i].key) {
+ apr_table_unset(temp, entries[i].key);
+ }
}
-
- /* at this point, all the PerlSetVar merging has happened. add in the
- * add (child) PerlAddVar entries and we're done
- */
- merged_config_vars = apr_table_overlay(p, base, add);
-
- return merged_config_vars;
+
+ return apr_table_overlay(p, temp, add);
}
#define merge_handlers(merge_flag, array) \
@@ -141,18 +121,10 @@
merge_table_overlap_item(SetEnv);
/* this is where we merge PerlSetVar and PerlAddVar together */
- mrg->configvars = merge_table_config_vars(p,
- base->configvars,
- add->setvars, add->addvars);
-
- /* note we don't care about merging dcfg->setvars or dcfg->addvars
- * specifically - what is important to merge is dfcg->configvars.
- * but we need to keep track of the entries for this config, so
- * the merged values are simply the values for the add (current)
- * configuration.
- */
- mrg->setvars = add->setvars;
- mrg->addvars = add->addvars;
+ mrg->configvars = merge_config_add_vars(p,
+ base->configvars,
+ add->setvars, add->configvars);
+ merge_table_overlap_item(setvars);
/* XXX: check if Perl*Handler is disabled */
for (i=0; i < MP_HANDLER_NUM_PER_DIR; i++) {
@@ -187,7 +159,6 @@
scfg->argv = apr_array_make(p, 2, sizeof(char *));
scfg->setvars = apr_table_make(p, 2);
- scfg->addvars = apr_table_make(p, 2);
scfg->configvars = apr_table_make(p, 2);
scfg->PassEnv = apr_table_make(p, 2);
@@ -223,7 +194,6 @@
dcfg->flags = modperl_options_new(p, MpDirType);
dcfg->setvars = apr_table_make(p, 2);
- dcfg->addvars = apr_table_make(p, 2);
dcfg->configvars = apr_table_make(p, 2);
dcfg->SetEnv = apr_table_make(p, 2);
@@ -320,18 +290,10 @@
merge_table_overlap_item(PassEnv);
/* this is where we merge PerlSetVar and PerlAddVar together */
- mrg->configvars = merge_table_config_vars(p,
- base->configvars,
- add->setvars, add->addvars);
-
- /* note we don't care about merging dcfg->setvars or dcfg->addvars
- * specifically - what is important to merge is dfcg->configvars.
- * but we need to keep track of the entries for this config, so
- * the merged values are simply the values for the add (current)
- * configuration.
- */
- mrg->setvars = add->setvars;
- mrg->addvars = add->addvars;
+ mrg->configvars = merge_config_add_vars(p,
+ base->configvars,
+ add->setvars, add->configvars);
+ merge_table_overlap_item(setvars);
merge_item(server);
1.78 +0 -2 modperl-2.0/src/modules/perl/modperl_types.h
Index: modperl_types.h
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_types.h,v
retrieving revision 1.77
retrieving revision 1.78
diff -u -r1.77 -r1.78
--- modperl_types.h 18 Sep 2004 04:33:34 -0000 1.77
+++ modperl_types.h 20 Sep 2004 18:14:48 -0000 1.78
@@ -127,7 +127,6 @@
typedef struct {
MpHV *setvars;
- MpHV *addvars;
MpHV *configvars;
MpHV *SetEnv;
MpHV *PassEnv;
@@ -159,7 +158,6 @@
MpAV *handlers_per_dir[MP_HANDLER_NUM_PER_DIR];
MpHV *SetEnv;
MpHV *setvars;
- MpHV *addvars;
MpHV *configvars;
modperl_options_t *flags;
#ifdef USE_ITHREADS
1.8 +0 -3 modperl-2.0/t/response/TestModperl/merge.pm
Index: merge.pm
===================================================================
RCS file: /home/cvs/modperl-2.0/t/response/TestModperl/merge.pm,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- merge.pm 9 Jul 2004 18:53:01 -0000 1.7
+++ merge.pm 20 Sep 2004 18:14:48 -0000 1.8
@@ -88,9 +88,6 @@
if ($uri =~ m/(merge3)/) {
$hash = $1;
-
- # skip .htaccess merges for now - they are still broken
- plan tests => 10, under_construction;
} elsif ($uri =~ m/(merge2)/) {
$hash = $1;
} else {