16 static void group_add_unallocated_utilization(GHashTable * all_utilization,
pe_resource_t * rsc,
26 utilization_value(
const char *s)
42 do_compare_capacity1(gpointer key, gpointer value, gpointer user_data)
44 int node1_capacity = 0;
45 int node2_capacity = 0;
46 struct compare_data *
data = user_data;
48 node1_capacity = utilization_value(value);
49 node2_capacity = utilization_value(g_hash_table_lookup(
data->node2->details->utilization, key));
51 if (node1_capacity > node2_capacity) {
53 }
else if (node1_capacity < node2_capacity) {
59 do_compare_capacity2(gpointer key, gpointer value, gpointer user_data)
61 int node1_capacity = 0;
62 int node2_capacity = 0;
63 struct compare_data *
data = user_data;
65 if (g_hash_table_lookup_extended(
data->node1->details->utilization, key, NULL, NULL)) {
70 node2_capacity = utilization_value(value);
72 if (node1_capacity > node2_capacity) {
74 }
else if (node1_capacity < node2_capacity) {
85 struct compare_data
data;
97 struct calculate_data {
98 GHashTable *current_utilization;
103 do_calculate_utilization(gpointer key, gpointer value, gpointer user_data)
105 const char *current = NULL;
107 struct calculate_data *
data = user_data;
109 current = g_hash_table_lookup(
data->current_utilization, key);
111 result = pcmk__itoa(utilization_value(current) + utilization_value(value));
112 g_hash_table_replace(
data->current_utilization, strdup(key), result);
114 }
else if (current) {
115 result = pcmk__itoa(utilization_value(current) - utilization_value(value));
116 g_hash_table_replace(
data->current_utilization, strdup(key), result);
125 GHashTable * utilization, gboolean plus)
127 struct calculate_data
data;
129 data.current_utilization = current_utilization;
132 g_hash_table_foreach(utilization, do_calculate_utilization, &
data);
136 struct capacity_data {
143 check_capacity(gpointer key, gpointer value, gpointer user_data)
147 struct capacity_data *
data = user_data;
149 required = utilization_value(value);
150 remaining = utilization_value(g_hash_table_lookup(
data->node->details->utilization, key));
152 if (required > remaining) {
156 crm_debug(
"Node %s does not have enough %s for %s: required=%d remaining=%d",
157 data->node->details->uname, (
char *)key,
data->rsc_id, required, remaining);
158 data->is_enough = FALSE;
163 have_enough_capacity(
pe_node_t * node,
const char * rsc_id, GHashTable * utilization)
165 struct capacity_data
data;
168 data.rsc_id = rsc_id;
169 data.is_enough = TRUE;
171 g_hash_table_foreach(utilization, check_capacity, &
data);
173 return data.is_enough;
178 native_add_unallocated_utilization(GHashTable * all_utilization,
pe_resource_t * rsc)
188 add_unallocated_utilization(GHashTable * all_utilization,
pe_resource_t * rsc,
196 pe_rsc_trace(orig_rsc,
"%s: Adding %s as colocated utilization",
197 orig_rsc->
id, rsc->
id);
198 native_add_unallocated_utilization(all_utilization, rsc);
201 pe_rsc_trace(orig_rsc,
"%s: Adding %s as colocated utilization",
202 orig_rsc->
id, rsc->
id);
203 group_add_unallocated_utilization(all_utilization, rsc, all_rscs);
205 }
else if (pe_rsc_is_clone(rsc)) {
206 GList *gIter1 = NULL;
207 gboolean existing = FALSE;
211 for (; gIter1 != NULL; gIter1 = gIter1->next) {
213 GList *gIter2 = NULL;
215 if (g_list_find(all_rscs, child)) {
221 for (; gIter2 != NULL; gIter2 = gIter2->next) {
224 if (g_list_find(all_rscs, grandchild)) {
225 pe_rsc_trace(orig_rsc,
"%s: Adding %s as colocated utilization",
226 orig_rsc->
id, child->
id);
227 add_unallocated_utilization(all_utilization, child, all_rscs, orig_rsc);
236 if (!existing && (rsc->
children != NULL)) {
239 pe_rsc_trace(orig_rsc,
"%s: Adding %s as colocated utilization",
240 orig_rsc->
id,
ID(first_child->
xml));
241 add_unallocated_utilization(all_utilization, first_child, all_rscs, orig_rsc);
247 sum_unallocated_utilization(
pe_resource_t * rsc, GList *colocated_rscs)
250 GList *all_rscs = NULL;
253 all_rscs = g_list_copy(colocated_rscs);
254 if (g_list_find(all_rscs, rsc) == FALSE) {
255 all_rscs = g_list_append(all_rscs, rsc);
258 for (gIter = all_rscs; gIter != NULL; gIter = gIter->next) {
265 pe_rsc_trace(rsc,
"%s: Processing unallocated colocated %s", rsc->
id, listed_rsc->
id);
266 add_unallocated_utilization(all_utilization, listed_rsc, all_rscs, rsc);
269 g_list_free(all_rscs);
271 return all_utilization;
277 CRM_CHECK(rsc && prefer && data_set,
return);
280 GList *colocated_rscs = NULL;
281 gboolean any_capable = FALSE;
285 if (colocated_rscs) {
286 GHashTable *unallocated_utilization = NULL;
291 unallocated_utilization = sum_unallocated_utilization(rsc, colocated_rscs);
294 while (g_hash_table_iter_next(&iter, NULL, (
void **)&node)) {
299 if (have_enough_capacity(node, rscs_id, unallocated_utilization)) {
303 if (most_capable_node == NULL ||
306 most_capable_node = node;
312 while (g_hash_table_iter_next(&iter, NULL, (
void **)&node)) {
317 if (have_enough_capacity(node, rscs_id, unallocated_utilization) == FALSE) {
319 "Resource %s and its colocated resources" 320 " cannot be allocated to node %s: not enough capacity",
321 rsc->
id, node->details->uname);
326 }
else if (*prefer == NULL) {
327 *prefer = most_capable_node;
330 if (unallocated_utilization) {
331 g_hash_table_destroy(unallocated_utilization);
334 g_list_free(colocated_rscs);
338 if (any_capable == FALSE) {
340 while (g_hash_table_iter_next(&iter, NULL, (
void **)&node)) {
345 if (have_enough_capacity(node, rsc->
id, rsc->
utilization) == FALSE) {
347 "Resource %s cannot be allocated to node %s:" 348 " not enough capacity",
349 rsc->
id, node->details->uname);
358 #define VARIANT_GROUP 1 362 group_add_unallocated_utilization(GHashTable * all_utilization,
pe_resource_t * rsc,
365 group_variant_data_t *group_data = NULL;
367 get_group_variant_data(group_data, rsc);
368 if (group_data->colocated || pe_rsc_is_clone(rsc->
parent)) {
371 for (; gIter != NULL; gIter = gIter->next) {
375 g_list_find(all_rscs, child_rsc) == FALSE) {
376 native_add_unallocated_utilization(all_utilization, child_rsc);
381 if (group_data->first_child &&
383 g_list_find(all_rscs, group_data->first_child) == FALSE) {
384 native_add_unallocated_utilization(all_utilization, group_data->first_child);
#define CRM_CHECK(expr, failure_action)
void process_utilization(pe_resource_t *rsc, pe_node_t **prefer, pe_working_set_t *data_set)
#define pe_rsc_debug(rsc, fmt, args...)
#define pe__show_node_weights(level, rsc, text, nodes, data_set)
int pcmk__scan_min_int(const char *text, int *result, int minimum)
void calculate_utilization(GHashTable *current_utilization, GHashTable *utilization, gboolean plus)
resource_alloc_functions_t * cmds
void resource_location(pe_resource_t *rsc, pe_node_t *node, int score, const char *tag, pe_working_set_t *data_set)
gboolean can_run_resources(const pe_node_t *node)
#define pe_rsc_provisional
#define crm_debug(fmt, args...)
int compare_capacity(const pe_node_t *node1, const pe_node_t *node2)
GList *(* colocated_resources)(pe_resource_t *rsc, pe_resource_t *orig_rsc, GList *colocated_rscs)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
struct pe_node_shared_s * details
enum pe_obj_types variant
const char * placement_strategy
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
#define pe_rsc_trace(rsc, fmt, args...)
GHashTable * allowed_nodes