diff --git a/include/crm/pengine/complex.h b/include/crm/pengine/complex.h index effa44f..1d010f4 100644 --- a/include/crm/pengine/complex.h +++ b/include/crm/pengine/complex.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2019 the Pacemaker project contributors + * Copyright 2004-2020 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -19,6 +19,9 @@ extern "C" { #include // pe_node_t, pe_resource_t, etc. extern resource_object_functions_t resource_class_functions[]; + +GHashTable *pe_rsc_params(pe_resource_t *rsc, pe_node_t *node, + pe_working_set_t *data_set); void get_meta_attributes(GHashTable * meta_hash, pe_resource_t *rsc, pe_node_t *node, pe_working_set_t *data_set); void get_rsc_attributes(GHashTable *meta_hash, pe_resource_t *rsc, diff --git a/include/crm/pengine/pe_types.h b/include/crm/pengine/pe_types.h index 59d5ce8..5529714 100644 --- a/include/crm/pengine/pe_types.h +++ b/include/crm/pengine/pe_types.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2020 the Pacemaker project contributors + * Copyright 2004-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -371,6 +371,12 @@ struct pe_resource_s { pe_node_t *lock_node; // Resource is shutdown-locked to this node time_t lock_time; // When shutdown lock started + /* Resource parameters may have node-attribute-based rules, which means the + * values can vary by node. This table is a cache of parameter name/value + * tables for each node (as needed). Use pe_rsc_params() to get the table + * for a given node. + */ + GHashTable *parameter_cache; // Key = node name, value = parameters table #if ENABLE_VERSIONED_ATTRS xmlNode *versioned_parameters; #endif diff --git a/lib/pengine/complex.c b/lib/pengine/complex.c index f3c696a..fad8fe2 100644 --- a/lib/pengine/complex.c +++ b/lib/pengine/complex.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2020 the Pacemaker project contributors + * Copyright 2004-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -388,6 +388,62 @@ detect_promotable(pe_resource_t *rsc) return FALSE; } +static void +free_params_table(gpointer data) +{ + g_hash_table_destroy((GHashTable *) data); +} + +/*! + * \brief Get a table of resource parameters + * + * \param[in] rsc Resource to query + * \param[in] node Node for evaluating rules (NULL for defaults) + * \param[in] data_set Cluster working set + * + * \return Hash table containing resource parameter names and values + * (or NULL if \p rsc or \p data_set is NULL) + * \note The returned table will be destroyed when the resource is freed, so + * callers should not destroy it. + */ +GHashTable * +pe_rsc_params(pe_resource_t *rsc, pe_node_t *node, pe_working_set_t *data_set) +{ + GHashTable *params_on_node = NULL; + + /* A NULL node is used to request the resource's default parameters + * (not evaluated for node), but we always want something non-NULL + * as a hash table key. + */ + const char *node_name = ""; + + // Sanity check + if ((rsc == NULL) || (data_set == NULL)) { + return NULL; + } + if ((node != NULL) && (node->details->uname != NULL)) { + node_name = node->details->uname; + } + + // Find the parameter table for given node + if (rsc->parameter_cache == NULL) { + rsc->parameter_cache = g_hash_table_new_full(crm_strcase_hash, + crm_strcase_equal, free, + free_params_table); + } else { + params_on_node = g_hash_table_lookup(rsc->parameter_cache, node_name); + } + + // If none exists yet, create one with parameters evaluated for node + if (params_on_node == NULL) { + params_on_node = crm_str_table_new(); + get_rsc_attributes(params_on_node, rsc, node, data_set); + g_hash_table_insert(rsc->parameter_cache, strdup(node_name), + params_on_node); + } + return params_on_node; +} + gboolean common_unpack(xmlNode * xml_obj, pe_resource_t ** rsc, pe_resource_t * parent, pe_working_set_t * data_set) @@ -822,6 +878,9 @@ common_free(pe_resource_t * rsc) if (rsc->parameters != NULL) { g_hash_table_destroy(rsc->parameters); } + if (rsc->parameter_cache != NULL) { + g_hash_table_destroy(rsc->parameter_cache); + } #if ENABLE_VERSIONED_ATTRS if (rsc->versioned_parameters != NULL) { free_xml(rsc->versioned_parameters);