pacemaker 3.0.1-16e74fc4da
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
scheduler.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2025 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU Lesser General Public License
7 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8 */
9
10#include <crm_internal.h>
11
12#include <stdint.h> // uint32_t
13#include <errno.h> // EINVAL
14#include <glib.h> // gboolean, FALSE, etc.
15#include <libxml/tree.h> // xmlNode
16
18
19uint32_t pcmk__warnings = 0;
20
33{
34 pcmk_scheduler_t *scheduler = calloc(1, sizeof(pcmk_scheduler_t));
35
36 if (scheduler == NULL) {
37 return NULL;
38 }
39 scheduler->priv = calloc(1, sizeof(pcmk__scheduler_private_t));
40 if (scheduler->priv == NULL) {
41 free(scheduler);
42 return NULL;
43 }
45 return scheduler;
46}
47
56void
77
86void
88{
89 if (scheduler == NULL) {
90 return;
91 }
92
93 /* Be careful about the order of freeing members. Many contain references to
94 * other members that will become dangling if those members are freed first.
95 * For example, the node name and ID of Pacemaker Remote nodes are pointers
96 * into resource objects. Ensure that earlier-freed members are not needed
97 * by any of the free functions for later-freed members.
98 */
99
100 scheduler->dc_node = NULL;
101
102 g_list_free_full(scheduler->nodes, pcmk__free_node);
103 scheduler->nodes = NULL;
104
105 // Do not reset local_node_name or out
106
108 scheduler->priv->now = NULL;
109
110 if (scheduler->priv->options != NULL) {
111 g_hash_table_destroy(scheduler->priv->options);
112 scheduler->priv->options = NULL;
113 }
114
115 scheduler->priv->fence_action = NULL;
121 scheduler->priv->rsc_defaults = NULL;
122 scheduler->priv->op_defaults = NULL;
123
124 g_list_free_full(scheduler->priv->resources, pcmk__free_resource);
125 scheduler->priv->resources = NULL;
126
127 if (scheduler->priv->templates != NULL) {
128 g_hash_table_destroy(scheduler->priv->templates);
129 scheduler->priv->templates = NULL;
130 }
131 if (scheduler->priv->tags != NULL) {
132 g_hash_table_destroy(scheduler->priv->tags);
133 scheduler->priv->tags = NULL;
134 }
135
136 g_list_free_full(scheduler->priv->actions, pcmk__free_action);
137 scheduler->priv->actions = NULL;
138
139 if (scheduler->priv->singletons != NULL) {
140 g_hash_table_destroy(scheduler->priv->singletons);
141 scheduler->priv->singletons = NULL;
142 }
143
145 scheduler->priv->failed = NULL;
146
148
149 g_list_free(scheduler->priv->stop_needed);
150 scheduler->priv->stop_needed = NULL;
151
152 g_list_free_full(scheduler->priv->location_constraints,
155
156 g_list_free_full(scheduler->priv->colocation_constraints, free);
158
159 g_list_free_full(scheduler->priv->ordering_constraints,
162
163 if (scheduler->priv->ticket_constraints != NULL) {
164 g_hash_table_destroy(scheduler->priv->ticket_constraints);
166 }
167
172
174 scheduler->priv->graph = NULL;
175
177
179 scheduler->input = NULL;
180
182
185}
186
192void
194{
195 if (scheduler != NULL) {
198 free(scheduler->priv);
199 free(scheduler);
200 }
201}
202
213{
214 return (scheduler == NULL)? NULL : scheduler->dc_node;
215}
216
227{
228 if (scheduler == NULL) {
229 return pcmk_no_quorum_stop; // The default
230 }
232}
233
245int
247{
248 if (scheduler == NULL) {
249 return EINVAL;
250 }
251 scheduler->input = cib;
252 return pcmk_rc_ok;
253}
254
263bool
265{
266 if (scheduler == NULL) {
267 return false;
268 }
270}
271
282pcmk_find_node(const pcmk_scheduler_t *scheduler, const char *node_name)
283{
284 if ((scheduler == NULL) || (node_name == NULL)) {
285 return NULL;
286 }
287 return pcmk__find_node_in_list(scheduler->nodes, node_name);
288}
289
299time_t
301{
302 if (scheduler == NULL) {
303 return time(NULL);
304 }
305 if (scheduler->priv->now == NULL) {
306 crm_trace("Scheduler 'now' set to current time");
307 scheduler->priv->now = crm_time_new(NULL);
308 }
310}
311
320void
322 const char *reason)
323{
324 pcmk__assert(scheduler != NULL);
325
327 && ((scheduler->priv->recheck_by == 0)
328 || (scheduler->priv->recheck_by > recheck))) {
329 scheduler->priv->recheck_by = recheck;
330 crm_debug("Updated next scheduler recheck to %s for %s",
331 pcmk__trim(ctime(&recheck)),
332 pcmk__s(reason, "some reason"));
333 }
334}
335
336/* Fail count clearing for parameter changes normally happens when unpacking
337 * history, before resources are unpacked. However, for bundles using the
338 * REMOTE_CONTAINER_HACK, we can't check the conditions until after unpacking
339 * the bundle, so those parameter checks are deferred using the APIs below.
340 */
341
342// History entry to be checked later for fail count clearing
343struct param_check {
344 const xmlNode *rsc_history; // History entry XML
345 pcmk_resource_t *rsc; // Resource corresponding to history entry
346 pcmk_node_t *node; // Node corresponding to history entry
347 enum pcmk__check_parameters check_type; // What needs checking
348};
349
359void
360pcmk__add_param_check(const xmlNode *rsc_history, pcmk_resource_t *rsc,
361 pcmk_node_t *node, enum pcmk__check_parameters flag)
362{
363 struct param_check *param_check = NULL;
364
365 CRM_CHECK((rsc_history != NULL) && (rsc != NULL) && (node != NULL), return);
366
367 crm_trace("Deferring checks of %s until after assignment",
368 pcmk__xe_id(rsc_history));
369 param_check = pcmk__assert_alloc(1, sizeof(struct param_check));
370 param_check->rsc_history = rsc_history;
371 param_check->rsc = rsc;
372 param_check->node = node;
373 param_check->check_type = flag;
374
376 g_list_prepend(rsc->priv->scheduler->priv->param_check, param_check);
377}
378
386void
388 void (*cb)(pcmk_resource_t*, pcmk_node_t*,
389 const xmlNode*,
391{
392 CRM_CHECK((scheduler != NULL) && (cb != NULL), return);
393
394 for (GList *item = scheduler->priv->param_check;
395 item != NULL; item = item->next) {
396 struct param_check *param_check = item->data;
397
398 cb(param_check->rsc, param_check->node, param_check->rsc_history,
399 param_check->check_type);
400 }
401}
402
409void
411{
412 if ((scheduler != NULL) && (scheduler->priv->param_check != NULL)) {
413 g_list_free_full(scheduler->priv->param_check, free);
414 scheduler->priv->param_check = NULL;
415 }
416}
void pcmk__free_action_relation(gpointer user_data)
void pcmk__free_action(gpointer user_data)
Definition actions.c:189
#define pcmk__assert_alloc(nmemb, size)
Definition internal.h:246
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:80
long long crm_time_get_seconds_since_epoch(const crm_time_t *dt)
Definition iso8601.c:374
void crm_time_free(crm_time_t *dt)
Definition iso8601.c:150
crm_time_t * crm_time_new(const char *string)
Definition iso8601.c:112
void pcmk__free_location(gpointer user_data)
Definition location.c:24
#define CRM_CHECK(expr, failure_action)
Definition logging.h:213
#define crm_debug(fmt, args...)
Definition logging.h:368
#define crm_trace(fmt, args...)
Definition logging.h:370
bool pcmk__config_has_error
Definition utils.c:43
pcmk__warnings
bool pcmk__config_has_warning
Definition utils.c:44
pcmk_scheduler_t * scheduler
pcmk_node_t * pcmk__find_node_in_list(const GList *nodes, const char *node_name)
Definition nodes.c:198
void pcmk__free_node(gpointer user_data)
Definition nodes.c:22
void pcmk__free_resource(gpointer user_data)
Definition resources.c:25
@ pcmk_rc_ok
Definition results.h:159
#define pcmk__assert(expr)
int pcmk_set_scheduler_cib(pcmk_scheduler_t *scheduler, xmlNode *cib)
Definition scheduler.c:246
void pcmk__set_scheduler_defaults(pcmk_scheduler_t *scheduler)
Definition scheduler.c:57
bool pcmk_has_quorum(const pcmk_scheduler_t *scheduler)
Definition scheduler.c:264
void pcmk_free_scheduler(pcmk_scheduler_t *scheduler)
Free scheduler data.
Definition scheduler.c:193
pcmk_scheduler_t * pcmk_new_scheduler(void)
Create a new object to hold scheduler data.
Definition scheduler.c:32
pcmk_node_t * pcmk_find_node(const pcmk_scheduler_t *scheduler, const char *node_name)
Find a node by name in scheduler data.
Definition scheduler.c:282
void pcmk__free_param_checks(pcmk_scheduler_t *scheduler)
Definition scheduler.c:410
void pcmk_reset_scheduler(pcmk_scheduler_t *scheduler)
Reset scheduler data to defaults.
Definition scheduler.c:87
time_t pcmk__scheduler_epoch_time(pcmk_scheduler_t *scheduler)
Definition scheduler.c:300
void pcmk__add_param_check(const xmlNode *rsc_history, pcmk_resource_t *rsc, pcmk_node_t *node, enum pcmk__check_parameters flag)
Definition scheduler.c:360
pcmk_node_t * pcmk_get_dc(const pcmk_scheduler_t *scheduler)
Definition scheduler.c:212
enum pe_quorum_policy pcmk_get_no_quorum_policy(const pcmk_scheduler_t *scheduler)
Definition scheduler.c:226
void pcmk__foreach_param_check(pcmk_scheduler_t *scheduler, void(*cb)(pcmk_resource_t *, pcmk_node_t *, const xmlNode *, enum pcmk__check_parameters))
Definition scheduler.c:387
void pcmk__update_recheck_time(time_t recheck, pcmk_scheduler_t *scheduler, const char *reason)
Definition scheduler.c:321
Scheduler API.
pe_quorum_policy
Possible responses to loss of quorum.
Definition scheduler.h:38
@ pcmk_no_quorum_stop
Stop all resources in partition.
Definition scheduler.h:40
pcmk__check_parameters
#define pcmk__set_scheduler_flags(scheduler, flags_to_set)
@ pcmk__sched_quorate
@ pcmk__sched_stop_removed_resources
@ pcmk__sched_cancel_removed_actions
@ pcmk__sched_symmetric_cluster
@ pcmk__sched_concurrent_fencing
char * pcmk__trim(char *str)
Definition strings.c:530
pcmk_scheduler_t * scheduler
pcmk__resource_private_t * priv
Definition resources.h:61
pcmk_node_t * dc_node
Definition scheduler.h:85
pcmk__scheduler_private_t * priv
Definition scheduler.h:99
enum pe_quorum_policy no_quorum_policy
Definition scheduler.h:93
GList * nodes
Definition scheduler.h:97
xmlNode * input
Definition scheduler.h:81
uint64_t flags
Definition scheduler.h:89
void pcmk__xml_free(xmlNode *xml)
Definition xml.c:816