where we can enable / disable flatten / nested pairs at run time.
schedule->stats_interval = config->stats_interval;
schedule->network.max_outstanding = config->max_requests;
- schedule->worker.max_requests = config->max_requests;
- schedule->worker.max_request_time = config->max_request_time;
+
+#define COPY(_x) schedule->worker._x = config->_x
+ COPY(max_requests);
+ COPY(max_request_time);
+ COPY(unflatten_after_decode);
+ COPY(unflatten_before_encode);
+ COPY(flatten_before_encode);
/*
* Single server mode: use the global event list.
ssize_t slen = 0;
fr_listen_t const *listen = request->async->listen;
+ if (worker->config.flatten_before_encode) {
+ fr_pair_flatten(request->pair_list.reply);
+
+ } else if (worker->config.unflatten_before_encode) {
+ fr_pair_unflatten(request->pair_list.reply);
+ } /* else noop */
+
if (listen->app->encode) {
slen = listen->app->encode(listen->app_instance, request,
reply->m.data, reply->m.rb_size);
return;
}
+ if (worker->config.unflatten_after_decode) {
+ fr_pair_unflatten(request->pair_list.request);
+ }
+
/*
* Set the entry point for this virtual server.
*/
fr_time_delta_t max_request_time; //!< maximum time a request can be processed
+ bool unflatten_after_decode; //!< the worker will call "unflatten" after protocol decoding
+ bool flatten_before_encode; //!< the worker will call "flatten" before all encoding
+ bool unflatten_before_encode; //!< the worker will call "unflatten" before all encoding
+
size_t talloc_pool_size; //!< for each request
} fr_worker_config_t;
CONF_PARSER_TERMINATOR
};
+static const CONF_PARSER migrate_config[] = {
+ { FR_CONF_OFFSET("unflatten_after_decode", FR_TYPE_BOOL | FR_TYPE_HIDDEN, main_config_t, unflatten_after_decode) },
+ { FR_CONF_OFFSET("unflatten_before_encode", FR_TYPE_BOOL | FR_TYPE_HIDDEN, main_config_t, unflatten_before_encode) },
+ { FR_CONF_OFFSET("flatten_before_encode", FR_TYPE_BOOL | FR_TYPE_HIDDEN, main_config_t, flatten_before_encode) },
+ { FR_CONF_OFFSET("tmpl_tokenize_all_nested", FR_TYPE_BOOL | FR_TYPE_HIDDEN, main_config_t, tmpl_tokenize_all_nested) },
+ { FR_CONF_OFFSET("parse_new_conditions", FR_TYPE_BOOL | FR_TYPE_HIDDEN, main_config_t, parse_new_conditions) },
+ { FR_CONF_OFFSET("use_new_conditions", FR_TYPE_BOOL | FR_TYPE_HIDDEN, main_config_t, use_new_conditions) },
+ CONF_PARSER_TERMINATOR
+};
+
static const CONF_PARSER server_config[] = {
/*
* FIXME: 'prefix' is the ONLY one which should be
{ FR_CONF_POINTER("thread", FR_TYPE_SUBSECTION, NULL), .subcs = (void const *) thread_config, .ident2 = CF_IDENT_ANY },
+ { FR_CONF_POINTER("migrate", FR_TYPE_SUBSECTION, NULL), .subcs = (void const *) migrate_config, .ident2 = CF_IDENT_ANY },
+
CONF_PARSER_TERMINATOR
};
uint32_t max_workers; //!< for the scheduler
fr_time_delta_t stats_interval; //!< for the scheduler
+ /*
+ * Migration tools
+ */
+ bool unflatten_after_decode; //!< the worker will call "unflatten" after protocol decoding
+ bool flatten_before_encode; //!< the worker will call "flatten" before all encoding
+ bool unflatten_before_encode; //!< the worker will call "unflatten" before all encoding
+ bool tmpl_tokenize_all_nested; //!< tmpl_tokenize will create nested tmpls instead of flat ones
+ bool parse_new_conditions; //!< the new xlat expressions will be parsed, but not used.
+ bool use_new_conditions; //!< the new xlat expressions will be used for conditions, instead of the old code
};
void main_config_name_set_default(main_config_t *config, char const *name, bool overwrite_config);
* each tmpl talloc pool, unless the attribute
* reference list contains a group, there's no performance
* penalty in repeatedly allocating and freeing this ar.
+ *
+ * Flatten / nested migration hack. :(
*/
- if ((filter == TMPL_ATTR_REF_NO_FILTER) && (ar->type == TMPL_ATTR_TYPE_NORMAL)) {
+ if ((main_config && main_config->tmpl_tokenize_all_nested) || ((filter == TMPL_ATTR_REF_NO_FILTER) && (ar->type == TMPL_ATTR_TYPE_NORMAL))) {
TALLOC_FREE(ar);
} else {
our_parent = da; /* Only update the parent if we're not stripping */
return XLAT_ACTION_DONE;
}
+/** Flatten a given group.
+ *
+ * This is a temporary function for migration purposes
+ *
+ * Example:
+@verbatim
+"%(flatten:&request)"
+@endverbatim
+ *
+ * @ingroup xlat_functions
+ */
+static xlat_action_t xlat_func_flatten(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out,
+ UNUSED xlat_ctx_t const *xctx,
+ request_t *request, fr_value_box_list_t *in)
+{
+ fr_pair_t *vp;
+ tmpl_t *vpt;
+ fr_value_box_t *attr = fr_dlist_head(in);
+ char const *fmt;
+
+ fmt = attr->vb_strvalue;
+ if (tmpl_afrom_attr_str(request, NULL, &vpt, fmt,
+ &(tmpl_rules_t){
+ .attr = {
+ .dict_def = request->dict,
+ .prefix = TMPL_ATTR_REF_PREFIX_AUTO
+ }
+ }) <= 0) {
+ RPEDEBUG("Invalid input");
+ return XLAT_ACTION_FAIL;
+ }
+
+ if ((tmpl_find_vp(&vp, request, vpt) < 0) ||
+ (vp->da->type != FR_TYPE_GROUP)) {
+ REDEBUG("Can't find '%s', or it's not a group", fmt);
+ talloc_free(vpt);
+ return XLAT_ACTION_FAIL;
+ }
+
+ fr_pair_flatten(vp);
+
+ talloc_free(vpt);
+
+ return XLAT_ACTION_DONE;
+}
+
+/** Unflatten a given group.
+ *
+ * This is a temporary function for migration purposes
+ *
+ * Example:
+@verbatim
+"%(unflatten:&request)"
+@endverbatim
+ *
+ * @ingroup xlat_functions
+ */
+static xlat_action_t xlat_func_unflatten(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out,
+ UNUSED xlat_ctx_t const *xctx,
+ request_t *request, fr_value_box_list_t *in)
+{
+ fr_pair_t *vp;
+ tmpl_t *vpt;
+ fr_value_box_t *attr = fr_dlist_head(in);
+ char const *fmt;
+
+ fmt = attr->vb_strvalue;
+ if (tmpl_afrom_attr_str(request, NULL, &vpt, fmt,
+ &(tmpl_rules_t){
+ .attr = {
+ .dict_def = request->dict,
+ .prefix = TMPL_ATTR_REF_PREFIX_AUTO
+ }
+ }) <= 0) {
+ RPEDEBUG("Invalid input");
+ return XLAT_ACTION_FAIL;
+ }
+
+ if ((tmpl_find_vp(&vp, request, vpt) < 0) ||
+ (vp->da->type != FR_TYPE_GROUP)) {
+ REDEBUG("Can't find '%s', or it's not a group", fmt);
+ talloc_free(vpt);
+ return XLAT_ACTION_FAIL;
+ }
+
+ fr_pair_unflatten(vp);
+
+ talloc_free(vpt);
+
+ return XLAT_ACTION_DONE;
+}
+
static xlat_action_t xlat_func_untaint(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out,
UNUSED xlat_ctx_t const *xctx,
UNUSED request_t *request, fr_value_box_list_t *in)
XLAT_REGISTER_ARGS("subst", xlat_func_subst, xlat_func_subst_args);
XLAT_REGISTER_ARGS("trigger", trigger_xlat, trigger_xlat_args);
+ /*
+ * Temporary functions for migration.
+ */
+ XLAT_REGISTER_ARGS("flatten", xlat_func_flatten, xlat_func_debug_attr_args); /* takes an attribute reference */
+ XLAT_REGISTER_ARGS("unflatten", xlat_func_unflatten, xlat_func_debug_attr_args); /* takes an attribute reference */
+
xlat = xlat_register(NULL, "untaint", xlat_func_untaint, NULL);
xlat_internal(xlat);
xlat = xlat_register(NULL, "taint", xlat_func_taint, NULL);
--- /dev/null
+#
+# PRE: edit-leaf-star
+#
+&Tmp-Group-0.Tmp-Integer-0 := { 1, 3, 5, 7, 11 }
+&Tmp-Integer-1 := 0
+
+#
+# Do operations on sets of inputs.
+#
+&Tmp-Integer-1 += &Tmp-Group-0.Tmp-Integer-0[*]
+if (&Tmp-Integer-1 != 27) {
+ test_fail
+}
+
+&Tmp-Group-1 := &Tmp-Group-0
+&Tmp-Integer-1 := 0
+
+&Tmp-Integer-1 += &Tmp-Group-1.Tmp-Integer-0[*]
+if (&Tmp-Integer-1 != 27) {
+ test_fail
+}
+
+success