diff --git a/daemons/execd/cts-exec-helper.c b/daemons/execd/cts-exec-helper.c index a74f5993a6c..47ab5bbe382 100644 --- a/daemons/execd/cts-exec-helper.c +++ b/daemons/execd/cts-exec-helper.c @@ -467,7 +467,7 @@ generate_params(void) } // Calculate cluster status - scheduler = pe_new_working_set(); + scheduler = pcmk_new_scheduler(); if (scheduler == NULL) { crm_crit("Could not allocate scheduler data"); return ENOMEM; @@ -484,7 +484,7 @@ generate_params(void) |pcmk_rsc_match_basename); if (rsc == NULL) { crm_err("Resource does not exist in config"); - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); return EINVAL; } @@ -511,7 +511,7 @@ generate_params(void) } g_hash_table_destroy(meta); - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); return rc; } diff --git a/daemons/fenced/fenced_scheduler.c b/daemons/fenced/fenced_scheduler.c index 358b6264e42..8817cd47472 100644 --- a/daemons/fenced/fenced_scheduler.c +++ b/daemons/fenced/fenced_scheduler.c @@ -37,7 +37,7 @@ fenced_scheduler_init(void) return rc; } - scheduler = pe_new_working_set(); + scheduler = pcmk_new_scheduler(); if (scheduler == NULL) { pcmk__output_free(logger); return ENOMEM; @@ -95,7 +95,7 @@ fenced_scheduler_cleanup(void) pcmk__output_free(logger); scheduler->priv->out = NULL; } - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); scheduler = NULL; } } @@ -250,5 +250,5 @@ fenced_scheduler_run(xmlNode *cib) NULL); scheduler->input = NULL; // Wasn't a copy, so don't let API free it - pe_reset_working_set(scheduler); + pcmk_reset_scheduler(scheduler); } diff --git a/daemons/schedulerd/schedulerd_messages.c b/daemons/schedulerd/schedulerd_messages.c index 9e93fcd24cb..a51a47c9e91 100644 --- a/daemons/schedulerd/schedulerd_messages.c +++ b/daemons/schedulerd/schedulerd_messages.c @@ -23,9 +23,9 @@ static GHashTable *schedulerd_handlers = NULL; static pcmk_scheduler_t * -init_working_set(void) +init_scheduler(void) { - pcmk_scheduler_t *scheduler = pe_new_working_set(); + pcmk_scheduler_t *scheduler = pcmk_new_scheduler(); pcmk__mem_assert(scheduler); scheduler->priv->out = logger_out; @@ -66,7 +66,7 @@ handle_pecalc_request(pcmk__request_t *request) xmlNode *reply = NULL; bool is_repoke = false; bool process = true; - pcmk_scheduler_t *scheduler = init_working_set(); + pcmk_scheduler_t *scheduler = init_scheduler(); pcmk__ipc_send_ack(request->ipc_client, request->ipc_id, request->ipc_flags, PCMK__XE_ACK, NULL, CRM_EX_INDETERMINATE); @@ -165,7 +165,7 @@ handle_pecalc_request(pcmk__request_t *request) done: pcmk__xml_free(converted); - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); return reply; } diff --git a/include/crm/common/action_relation_internal.h b/include/crm/common/action_relation_internal.h index 2f594b3edf4..895bf29eca5 100644 --- a/include/crm/common/action_relation_internal.h +++ b/include/crm/common/action_relation_internal.h @@ -12,6 +12,7 @@ #include // bool #include // uint32_t +#include // gpointer #include // pcmk_resource_t, pcmk_action_t #ifdef __cplusplus @@ -181,6 +182,8 @@ typedef struct pcmk__related_action { #flags_to_clear); \ } while (0) +void pcmk__free_action_relation(gpointer user_data); + #ifdef __cplusplus } #endif diff --git a/include/crm/common/actions_internal.h b/include/crm/common/actions_internal.h index 3d025cd5b43..072aa1adafb 100644 --- a/include/crm/common/actions_internal.h +++ b/include/crm/common/actions_internal.h @@ -232,6 +232,7 @@ struct pcmk__action { GList *actions_after; }; +void pcmk__free_action(gpointer user_data); char *pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms); char *pcmk__notify_key(const char *rsc_id, const char *notify_type, const char *op_type); diff --git a/include/crm/common/location_internal.h b/include/crm/common/location_internal.h index 39aba91c4be..1ca3024c3c9 100644 --- a/include/crm/common/location_internal.h +++ b/include/crm/common/location_internal.h @@ -10,7 +10,7 @@ #ifndef PCMK__CRM_COMMON_LOCATION_INTERNAL__H #define PCMK__CRM_COMMON_LOCATION_INTERNAL__H -#include // GList +#include // gpointer, GList #include // enum pcmk__probe_mode #include // enum rsc_role_e @@ -29,6 +29,8 @@ typedef struct { GList *nodes; // Copies of affected nodes, with score } pcmk__location_t; +void pcmk__free_location(gpointer user_data); + #ifdef __cplusplus } #endif diff --git a/include/crm/common/nodes_internal.h b/include/crm/common/nodes_internal.h index 4e0dd866919..b8525758a3d 100644 --- a/include/crm/common/nodes_internal.h +++ b/include/crm/common/nodes_internal.h @@ -14,7 +14,7 @@ #include // bool #include // uint32_t, UINT32_C() -#include +#include // gpointer, GList, GHashTable #include #ifdef __cplusplus @@ -152,6 +152,8 @@ pcmk_node_t *pcmk__find_node_in_list(const GList *nodes, const char *node_name); (node)->priv->flags, (flags_to_clear), #flags_to_clear); \ } while (0) +void pcmk__free_node(gpointer user_data); + /*! * \internal * \brief Return a string suitable for logging as a node name diff --git a/include/crm/common/resources_internal.h b/include/crm/common/resources_internal.h index 87ac4c609c5..2200ee153b4 100644 --- a/include/crm/common/resources_internal.h +++ b/include/crm/common/resources_internal.h @@ -11,7 +11,7 @@ #define PCMK__CRM_COMMON_RESOURCES_INTERNAL__H #include // uint32_t -#include // gboolean, guint, GHashTable, GList +#include // gboolean, gpointer, guint, etc. #include // xmlNode #include // pcmk_resource_t @@ -442,6 +442,7 @@ struct pcmk__resource_private { const pcmk__assignment_methods_t *cmds; // Resource assignment methods }; +void pcmk__free_resource(gpointer user_data); const char *pcmk__multiply_active_text(const pcmk_resource_t *rsc); /*! diff --git a/include/crm/common/scheduler.h b/include/crm/common/scheduler.h index 5d12c9db285..86d0cd7d9ed 100644 --- a/include/crm/common/scheduler.h +++ b/include/crm/common/scheduler.h @@ -99,6 +99,10 @@ struct pcmk__scheduler { pcmk__scheduler_private_t *priv; //!< \internal For Pacemaker use only }; +pcmk_scheduler_t *pcmk_new_scheduler(void); +void pcmk_reset_scheduler(pcmk_scheduler_t *scheduler); +void pcmk_free_scheduler(pcmk_scheduler_t *scheduler); + pcmk_node_t *pcmk_get_dc(const pcmk_scheduler_t *scheduler); enum pe_quorum_policy pcmk_get_no_quorum_policy(const pcmk_scheduler_t *scheduler); diff --git a/include/crm/common/scheduler_internal.h b/include/crm/common/scheduler_internal.h index 39e806d92c1..8ff4eb98865 100644 --- a/include/crm/common/scheduler_internal.h +++ b/include/crm/common/scheduler_internal.h @@ -279,6 +279,20 @@ extern uint32_t pcmk__warnings; (scheduler)->flags, (flags_to_clear), #flags_to_clear); \ } while (0) +void pcmk__set_scheduler_defaults(pcmk_scheduler_t *scheduler); +time_t pcmk__scheduler_epoch_time(pcmk_scheduler_t *scheduler); +void pcmk__update_recheck_time(time_t recheck, pcmk_scheduler_t *scheduler, + const char *reason); + +void pcmk__add_param_check(const xmlNode *rsc_op, pcmk_resource_t *rsc, + pcmk_node_t *node, enum pcmk__check_parameters, + pcmk_scheduler_t *scheduler); +void pcmk__foreach_param_check(pcmk_scheduler_t *scheduler, + void (*cb)(pcmk_resource_t*, pcmk_node_t*, + const xmlNode*, + enum pcmk__check_parameters)); +void pcmk__free_param_checks(pcmk_scheduler_t *scheduler); + #ifdef __cplusplus } #endif diff --git a/include/crm/pengine/internal.h b/include/crm/pengine/internal.h index 41ef4dc2158..a9f4791cdbd 100644 --- a/include/crm/pengine/internal.h +++ b/include/crm/pengine/internal.h @@ -128,7 +128,6 @@ void pe__count_bundle(pcmk_resource_t *rsc); void common_free(pcmk_resource_t *rsc); pcmk_node_t *pe__copy_node(const pcmk_node_t *this_node); -time_t get_effective_time(pcmk_scheduler_t *scheduler); /* Failure handling utilities (from failcounts.c) */ @@ -231,8 +230,6 @@ GList *find_actions_exact(GList *input, const char *key, GList *pe__resource_actions(const pcmk_resource_t *rsc, const pcmk_node_t *node, const char *task, bool require_node); -extern void pe_free_action(pcmk_action_t *action); - void resource_location(pcmk_resource_t *rsc, const pcmk_node_t *node, int score, const char *tag, pcmk_scheduler_t *scheduler); @@ -336,18 +333,8 @@ const char *pe__add_bundle_remote_name(pcmk_resource_t *rsc, xmlNode *xml, const char *field); bool pe__is_universal_clone(const pcmk_resource_t *rsc, const pcmk_scheduler_t *scheduler); -void pe__add_param_check(const xmlNode *rsc_op, pcmk_resource_t *rsc, - pcmk_node_t *node, enum pcmk__check_parameters, - pcmk_scheduler_t *scheduler); -void pe__foreach_param_check(pcmk_scheduler_t *scheduler, - void (*cb)(pcmk_resource_t*, pcmk_node_t*, - const xmlNode*, - enum pcmk__check_parameters)); -void pe__free_param_checks(pcmk_scheduler_t *scheduler); bool pe__shutdown_requested(const pcmk_node_t *node); -void pe__update_recheck_time(time_t recheck, pcmk_scheduler_t *scheduler, - const char *reason); /*! * \internal diff --git a/include/crm/pengine/status.h b/include/crm/pengine/status.h index 80fae41ae41..4d894dc96ed 100644 --- a/include/crm/pengine/status.h +++ b/include/crm/pengine/status.h @@ -32,18 +32,6 @@ const char *rsc_printable_id(const pcmk_resource_t *rsc); // NOTE: sbd (as of at least 1.5.2) uses this gboolean cluster_status(pcmk_scheduler_t *scheduler); -// NOTE: sbd (as of at least 1.5.2) uses this -pcmk_scheduler_t *pe_new_working_set(void); - -// NOTE: sbd (as of at least 1.5.2) uses this -void pe_free_working_set(pcmk_scheduler_t *scheduler); - -void set_working_set_defaults(pcmk_scheduler_t *scheduler); -void cleanup_calculations(pcmk_scheduler_t *scheduler); - -// NOTE: sbd (as of at least 1.5.2) uses this -void pe_reset_working_set(pcmk_scheduler_t *scheduler); - pcmk_resource_t *pe_find_resource(GList *rsc_list, const char *id); pcmk_resource_t *pe_find_resource_with_flags(GList *rsc_list, const char *id, enum pe_find flags); diff --git a/include/crm/pengine/status_compat.h b/include/crm/pengine/status_compat.h index 5488bb8e7d4..af45129d2d4 100644 --- a/include/crm/pengine/status_compat.h +++ b/include/crm/pengine/status_compat.h @@ -27,6 +27,24 @@ extern "C" { * release. */ +// NOTE: sbd (as of at least 1.5.2) uses this +//! \deprecated Use pcmk_new_scheduler() instead +pcmk_scheduler_t *pe_new_working_set(void); + +// NOTE: sbd (as of at least 1.5.2) uses this +//! \deprecated Use pcmk_reset_scheduler() instead +void pe_reset_working_set(pcmk_scheduler_t *scheduler); + +//! \deprecated Use pcmk_reset_scheduler() instead +void cleanup_calculations(pcmk_scheduler_t *scheduler); + +//! \deprecated Use pcmk_reset_scheduler() instead +void set_working_set_defaults(pcmk_scheduler_t *scheduler); + +// NOTE: sbd (as of at least 1.5.2) uses this +//! \deprecated Use pcmk_free_scheduler() instead +void pe_free_working_set(pcmk_scheduler_t *scheduler); + // NOTE: sbd (as of at least 1.5.2) uses this //! \deprecated Use pcmk_find_node() with scheduler object instead pcmk_node_t *pe_find_node(const GList *node_list, const char *node_name); diff --git a/lib/common/Makefile.am b/lib/common/Makefile.am index 45fd0a0265e..32fdf0602a4 100644 --- a/lib/common/Makefile.am +++ b/lib/common/Makefile.am @@ -47,6 +47,7 @@ endif ## Library sources (*must* use += format for bumplibs) libcrmcommon_la_SOURCES = libcrmcommon_la_SOURCES += acl.c +libcrmcommon_la_SOURCES += action_relation.c libcrmcommon_la_SOURCES += actions.c libcrmcommon_la_SOURCES += agents.c libcrmcommon_la_SOURCES += alerts.c @@ -68,6 +69,7 @@ libcrmcommon_la_SOURCES += ipc_schedulerd.c libcrmcommon_la_SOURCES += ipc_server.c libcrmcommon_la_SOURCES += iso8601.c libcrmcommon_la_SOURCES += lists.c +libcrmcommon_la_SOURCES += location.c libcrmcommon_la_SOURCES += logging.c libcrmcommon_la_SOURCES += mainloop.c libcrmcommon_la_SOURCES += messages.c diff --git a/lib/common/action_relation.c b/lib/common/action_relation.c new file mode 100644 index 00000000000..22343cc5514 --- /dev/null +++ b/lib/common/action_relation.c @@ -0,0 +1,31 @@ +/* + * Copyright 2024 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU Lesser General Public License + * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. + */ + +#include + +#include // free() +#include // gpointer + +#include + +/*! + * \internal + * \brief Free an action relation + * + * \param[in,out] user_data Action relation to free + */ +void +pcmk__free_action_relation(gpointer user_data) +{ + pcmk__action_relation_t *relation = user_data; + + free(relation->task1); + free(relation->task2); + free(relation); +} diff --git a/lib/common/actions.c b/lib/common/actions.c index cbfe6ebe8d1..61076f50b13 100644 --- a/lib/common/actions.c +++ b/lib/common/actions.c @@ -179,6 +179,36 @@ pcmk__on_fail_text(enum pcmk__on_fail on_fail) return ""; } +/*! + * \internal + * \brief Free an action object + * + * \param[in,out] user_data Action object to free + */ +void +pcmk__free_action(gpointer user_data) +{ + pcmk_action_t *action = user_data; + + if (action == NULL) { + return; + } + g_list_free_full(action->actions_before, free); + g_list_free_full(action->actions_after, free); + if (action->extra != NULL) { + g_hash_table_destroy(action->extra); + } + if (action->meta != NULL) { + g_hash_table_destroy(action->meta); + } + pcmk__free_node_copy(action->node); + free(action->cancel_task); + free(action->reason); + free(action->task); + free(action->uuid); + free(action); +} + /*! * \brief Generate an operation key (RESOURCE_ACTION_INTERVAL) * diff --git a/lib/common/location.c b/lib/common/location.c new file mode 100644 index 00000000000..e0f7707024e --- /dev/null +++ b/lib/common/location.c @@ -0,0 +1,31 @@ +/* + * Copyright 2024 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU Lesser General Public License + * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. + */ + +#include + +#include // free() +#include // gpointer, g_list_free_full() + +#include + +/*! + * \internal + * \brief Free a location constraint + * + * \param[in,out] user_data Location constraint to free + */ +void +pcmk__free_location(gpointer user_data) +{ + pcmk__location_t *location = user_data; + + g_list_free_full(location->nodes, pcmk__free_node_copy); + free(location->id); + free(location); +} diff --git a/lib/common/nodes.c b/lib/common/nodes.c index fed31594649..4a059e6520c 100644 --- a/lib/common/nodes.c +++ b/lib/common/nodes.c @@ -12,6 +12,48 @@ #include // xmlNode #include +/*! + * \internal + * \brief Free a node object + * + * \param[in,out] user_data Node object to free + */ +void +pcmk__free_node(gpointer user_data) +{ + pcmk_node_t *node = user_data; + + if (node == NULL) { + return; + } + if (node->details == NULL) { + free(node); + return; + } + + /* This may be called after freeing resources, which means that we can't + * use node->private->name for Pacemaker Remote nodes. + */ + crm_trace("Freeing node %s", (pcmk__is_pacemaker_remote_node(node)? + "(guest or remote)" : pcmk__node_name(node))); + + if (node->priv->attrs != NULL) { + g_hash_table_destroy(node->priv->attrs); + } + if (node->priv->utilization != NULL) { + g_hash_table_destroy(node->priv->utilization); + } + if (node->priv->digest_cache != NULL) { + g_hash_table_destroy(node->priv->digest_cache); + } + g_list_free(node->details->running_rsc); + g_list_free(node->priv->assigned_resources); + free(node->priv); + free(node->details); + free(node->assign); + free(node); +} + /*! * \internal * \brief Free a copy of a node object diff --git a/lib/common/resources.c b/lib/common/resources.c index bfc3ddfc5b9..18890a99af2 100644 --- a/lib/common/resources.c +++ b/lib/common/resources.c @@ -15,6 +15,22 @@ #include #include +/*! + * \internal + * \brief Free a resource object + * + * \param[in,out] user_data Resource object to free + */ +void +pcmk__free_resource(gpointer user_data) +{ + pcmk_resource_t *rsc = user_data; + + if (rsc != NULL) { + rsc->priv->fns->free(rsc); + } +} + /*! * \internal * \brief Get a resource's ID diff --git a/lib/common/scheduler.c b/lib/common/scheduler.c index 0e73da7ba3e..78413e7da77 100644 --- a/lib/common/scheduler.c +++ b/lib/common/scheduler.c @@ -11,13 +11,194 @@ #include // uint32_t #include // EINVAL -#include // gboolean, FALSE +#include // gboolean, FALSE, etc. #include // xmlNode #include uint32_t pcmk__warnings = 0; +/*! + * \brief Create a new object to hold scheduler data + * + * \return New, initialized scheduler data, or NULL on memory error + * \note Only pcmk_scheduler_t objects created with this function (as opposed + * to statically declared or directly allocated) should be used with the + * functions in this library, to allow for future extensions to the + * data type. The caller is responsible for freeing the memory with + * pcmk_free_scheduler() when the instance is no longer needed. + */ +pcmk_scheduler_t * +pcmk_new_scheduler(void) +{ + pcmk_scheduler_t *scheduler = calloc(1, sizeof(pcmk_scheduler_t)); + + if (scheduler == NULL) { + return NULL; + } + scheduler->priv = calloc(1, sizeof(pcmk__scheduler_private_t)); + if (scheduler->priv == NULL) { + free(scheduler); + return NULL; + } + pcmk__set_scheduler_defaults(scheduler); + return scheduler; +} + +/*! + * \internal + * \brief Set non-zero default values in scheduler data + * + * \param[in,out] scheduler Scheduler data to modify + * + * \note Values that default to NULL or 0 will remain unchanged + */ +void +pcmk__set_scheduler_defaults(pcmk_scheduler_t *scheduler) +{ + pcmk__assert(scheduler != NULL); + scheduler->flags = 0U; +#if PCMK__CONCURRENT_FENCING_DEFAULT_TRUE + pcmk__set_scheduler_flags(scheduler, + pcmk__sched_symmetric_cluster + |pcmk__sched_concurrent_fencing + |pcmk__sched_stop_removed_resources + |pcmk__sched_cancel_removed_actions); +#else + pcmk__set_scheduler_flags(scheduler, + pcmk__sched_symmetric_cluster + |pcmk__sched_stop_removed_resources + |pcmk__sched_cancel_removed_actions); +#endif + scheduler->no_quorum_policy = pcmk_no_quorum_stop; + scheduler->priv->next_action_id = 1; + scheduler->priv->next_ordering_id = 1; +} + +/*! + * \brief Reset scheduler data to defaults + * + * Free scheduler data except the local node name and output object, and reset + * all other values to defaults, so the data is suitable for rerunning status + * + * \param[in,out] scheduler Scheduler data to reset + */ +void +pcmk_reset_scheduler(pcmk_scheduler_t *scheduler) +{ + CRM_CHECK(scheduler != NULL, return); + + /* Be careful about the order of freeing members. Many contain references to + * other members that will become dangling if those members are freed first. + * For example, the node name and ID of Pacemaker Remote nodes are pointers + * into resource objects. Ensure that earlier-freed members are not needed + * by any of the free functions for later-freed members. + */ + + pcmk__xml_free(scheduler->input); + scheduler->input = NULL; + + scheduler->dc_node = NULL; + + g_list_free_full(scheduler->nodes, pcmk__free_node); + scheduler->nodes = NULL; + + // Do not reset local_node_name or out + + crm_time_free(scheduler->priv->now); + scheduler->priv->now = NULL; + + if (scheduler->priv->options != NULL) { + g_hash_table_destroy(scheduler->priv->options); + scheduler->priv->options = NULL; + } + + scheduler->priv->fence_action = NULL; + scheduler->priv->fence_timeout_ms = 0U; + scheduler->priv->priority_fencing_ms = 0U; + scheduler->priv->shutdown_lock_ms = 0U; + scheduler->priv->node_pending_ms = 0U; + scheduler->priv->placement_strategy = NULL; + scheduler->priv->rsc_defaults = NULL; + scheduler->priv->op_defaults = NULL; + + g_list_free_full(scheduler->priv->resources, pcmk__free_resource); + scheduler->priv->resources = NULL; + + if (scheduler->priv->templates != NULL) { + g_hash_table_destroy(scheduler->priv->templates); + scheduler->priv->templates = NULL; + } + if (scheduler->priv->tags != NULL) { + g_hash_table_destroy(scheduler->priv->tags); + scheduler->priv->tags = NULL; + } + + g_list_free_full(scheduler->priv->actions, pcmk__free_action); + scheduler->priv->actions = NULL; + + if (scheduler->priv->singletons != NULL) { + g_hash_table_destroy(scheduler->priv->singletons); + scheduler->priv->singletons = NULL; + } + + pcmk__xml_free(scheduler->priv->failed); + scheduler->priv->failed = NULL; + + pcmk__free_param_checks(scheduler); + + g_list_free(scheduler->priv->stop_needed); + scheduler->priv->stop_needed = NULL; + + g_list_free_full(scheduler->priv->location_constraints, + pcmk__free_location); + scheduler->priv->location_constraints = NULL; + + g_list_free_full(scheduler->priv->colocation_constraints, free); + scheduler->priv->colocation_constraints = NULL; + + g_list_free_full(scheduler->priv->ordering_constraints, + pcmk__free_action_relation); + scheduler->priv->ordering_constraints = NULL; + + if (scheduler->priv->ticket_constraints != NULL) { + g_hash_table_destroy(scheduler->priv->ticket_constraints); + scheduler->priv->ticket_constraints = NULL; + } + + scheduler->priv->ninstances = 0; + scheduler->priv->blocked_resources = 0; + scheduler->priv->disabled_resources = 0; + scheduler->priv->recheck_by = 0; + + pcmk__xml_free(scheduler->priv->graph); + scheduler->priv->graph = NULL; + + scheduler->priv->synapse_count = 0; + + pcmk__set_scheduler_defaults(scheduler); + + /* @TODO We should probably reset pcmk__config_has_warning and + * pcmk__config_has_error as well + */ +} + +/*! + * \brief Free scheduler data + * + * \param[in,out] scheduler Scheduler data to free + */ +void +pcmk_free_scheduler(pcmk_scheduler_t *scheduler) +{ + if (scheduler != NULL) { + pcmk_reset_scheduler(scheduler); + free(scheduler->priv->local_node_name); + free(scheduler->priv); + free(scheduler); + } +} + /*! * \internal * \brief Get the Designated Controller node from scheduler data @@ -104,3 +285,133 @@ pcmk_find_node(const pcmk_scheduler_t *scheduler, const char *node_name) } return pcmk__find_node_in_list(scheduler->nodes, node_name); } + +/*! + * \internal + * \brief Get scheduler data's "now" in epoch time + * + * \param[in,out] scheduler Scheduler data + * + * \return Scheduler data's "now" as seconds since epoch (defaulting to current + * time) + */ +time_t +pcmk__scheduler_epoch_time(pcmk_scheduler_t *scheduler) +{ + if (scheduler == NULL) { + return time(NULL); + } + if (scheduler->priv->now == NULL) { + crm_trace("Scheduler 'now' set to current time"); + scheduler->priv->now = crm_time_new(NULL); + } + return crm_time_get_seconds_since_epoch(scheduler->priv->now); +} + +/*! + * \internal + * \brief Update "recheck by" time in scheduler data + * + * \param[in] recheck Epoch time when recheck should happen + * \param[in,out] scheduler Scheduler data + * \param[in] reason What time is being updated for (for logs) + */ +void +pcmk__update_recheck_time(time_t recheck, pcmk_scheduler_t *scheduler, + const char *reason) +{ + pcmk__assert(scheduler != NULL); + + if ((recheck > pcmk__scheduler_epoch_time(scheduler)) + && ((scheduler->priv->recheck_by == 0) + || (scheduler->priv->recheck_by > recheck))) { + scheduler->priv->recheck_by = recheck; + crm_debug("Updated next scheduler recheck to %s for %s", + pcmk__trim(ctime(&recheck)), + pcmk__s(reason, "some reason")); + } +} + +/* Fail count clearing for parameter changes normally happens when unpacking + * history, before resources are unpacked. However, for bundles using the + * REMOTE_CONTAINER_HACK, we can't check the conditions until after unpacking + * the bundle, so those parameter checks are deferred using the APIs below. + */ + +// History entry to be checked later for fail count clearing +struct param_check { + const xmlNode *rsc_history; // History entry XML + pcmk_resource_t *rsc; // Resource corresponding to history entry + pcmk_node_t *node; // Node corresponding to history entry + enum pcmk__check_parameters check_type; // What needs checking +}; + +/*! + * \internal + * \brief Add a deferred parameter check + * + * \param[in] rsc_history Resource history XML to check later + * \param[in] rsc Resource that history is for + * \param[in] node Node that history is for + * \param[in] flag What needs to be checked later + * \param[in,out] scheduler Scheduler data + */ +void +pcmk__add_param_check(const xmlNode *rsc_history, pcmk_resource_t *rsc, + pcmk_node_t *node, enum pcmk__check_parameters flag, + pcmk_scheduler_t *scheduler) +{ + struct param_check *param_check = NULL; + + CRM_CHECK((rsc_history != NULL) && (rsc != NULL) && (node != NULL) + && (scheduler != NULL), return); + + crm_trace("Deferring checks of %s until after assignment", + pcmk__xe_id(rsc_history)); + param_check = pcmk__assert_alloc(1, sizeof(struct param_check)); + param_check->rsc_history = rsc_history; + param_check->rsc = rsc; + param_check->node = node; + param_check->check_type = flag; + scheduler->priv->param_check = g_list_prepend(scheduler->priv->param_check, + param_check); +} + +/*! + * \internal + * \brief Call a function for each deferred parameter check + * + * \param[in,out] scheduler Scheduler data + * \param[in] cb Function to be called + */ +void +pcmk__foreach_param_check(pcmk_scheduler_t *scheduler, + void (*cb)(pcmk_resource_t*, pcmk_node_t*, + const xmlNode*, + enum pcmk__check_parameters)) +{ + CRM_CHECK((scheduler != NULL) && (cb != NULL), return); + + for (GList *item = scheduler->priv->param_check; + item != NULL; item = item->next) { + struct param_check *param_check = item->data; + + cb(param_check->rsc, param_check->node, param_check->rsc_history, + param_check->check_type); + } +} + +/*! + * \internal + * \brief Free all deferred parameter checks + * + * \param[in,out] scheduler Scheduler data + */ +void +pcmk__free_param_checks(pcmk_scheduler_t *scheduler) +{ + if ((scheduler != NULL) && (scheduler->priv->param_check != NULL)) { + g_list_free_full(scheduler->priv->param_check, free); + scheduler->priv->param_check = NULL; + } +} diff --git a/lib/common/tests/scheduler/Makefile.am b/lib/common/tests/scheduler/Makefile.am index 51bde6235ea..abb30df85dc 100644 --- a/lib/common/tests/scheduler/Makefile.am +++ b/lib/common/tests/scheduler/Makefile.am @@ -12,9 +12,12 @@ include $(top_srcdir)/mk/tap.mk include $(top_srcdir)/mk/unittest.mk # Add "_test" to the end of all test program names to simplify .gitignore. -check_PROGRAMS = pcmk_get_dc_test \ +check_PROGRAMS = pcmk__set_scheduler_defaults_test \ + pcmk__update_recheck_time_test \ + pcmk_get_dc_test \ pcmk_get_no_quorum_policy_test \ pcmk_has_quorum_test \ + pcmk_new_scheduler_test \ pcmk_set_scheduler_cib_test TESTS = $(check_PROGRAMS) diff --git a/lib/pengine/tests/status/set_working_set_defaults_test.c b/lib/common/tests/scheduler/pcmk__set_scheduler_defaults_test.c similarity index 76% rename from lib/pengine/tests/status/set_working_set_defaults_test.c rename to lib/common/tests/scheduler/pcmk__set_scheduler_defaults_test.c index 9743e1c7597..788d04bcf19 100644 --- a/lib/pengine/tests/status/set_working_set_defaults_test.c +++ b/lib/common/tests/scheduler/pcmk__set_scheduler_defaults_test.c @@ -18,13 +18,20 @@ #include "mock_private.h" static void -check_defaults(void **state) { - uint32_t flags; - pcmk_scheduler_t *scheduler = pcmk__assert_alloc(1, - sizeof(pcmk_scheduler_t)); +null_scheduler(void **state) +{ + pcmk__assert_asserts(pcmk__set_scheduler_defaults(NULL)); +} + +static void +check_defaults(void **state) +{ + uint32_t flags = 0U; + pcmk_scheduler_t *scheduler = NULL; + scheduler = pcmk__assert_alloc(1, sizeof(pcmk_scheduler_t)); scheduler->priv = pcmk__assert_alloc(1, sizeof(pcmk__scheduler_private_t)); - set_working_set_defaults(scheduler); + pcmk__set_scheduler_defaults(scheduler); flags = pcmk__sched_symmetric_cluster #if PCMK__CONCURRENT_FENCING_DEFAULT_TRUE @@ -39,12 +46,10 @@ check_defaults(void **state) { assert_int_equal(scheduler->no_quorum_policy, pcmk_no_quorum_stop); assert_int_equal(scheduler->flags, flags); - /* Avoid calling pe_free_working_set here so we don't artificially - * inflate the coverage numbers. - */ free(scheduler->priv); free(scheduler); } PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(null_scheduler), cmocka_unit_test(check_defaults)) diff --git a/lib/common/tests/scheduler/pcmk__update_recheck_time_test.c b/lib/common/tests/scheduler/pcmk__update_recheck_time_test.c new file mode 100644 index 00000000000..73448916453 --- /dev/null +++ b/lib/common/tests/scheduler/pcmk__update_recheck_time_test.c @@ -0,0 +1,79 @@ +/* + * Copyright 2024 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include // NULL +#include // time_t + +#include +#include +#include + +static void +assert_recheck(time_t now_time, time_t orig_time, time_t update_time, + time_t expected_time, const char *reason) +{ + pcmk_scheduler_t *scheduler = pcmk_new_scheduler(); + + scheduler->priv->now = pcmk__copy_timet(now_time); + scheduler->priv->recheck_by = orig_time; + pcmk__update_recheck_time(update_time, scheduler, reason); + assert_int_equal(scheduler->priv->recheck_by, expected_time); + pcmk_free_scheduler(scheduler); +} + +// A NULL scheduler argument is invalid and should assert +static void +null_scheduler(void **state) +{ + pcmk__assert_asserts(pcmk__update_recheck_time(0, NULL, "reasons")); +} + +// Do not update recheck time if new value is before or equal to "now" +static void +too_early(void **state) +{ + // Recheck time is initially unset + assert_recheck(1423548000, 0, 1423547900, 0, NULL); + assert_recheck(1423548000, 0, 1423548000, 0, NULL); + + // Recheck time is initially set + assert_recheck(1423548000, 1423548100, 1423547900, 1423548100, NULL); + assert_recheck(1423548000, 1423548100, 1423548000, 1423548100, NULL); +} + +// Update recheck time if the existing value is 0 +static void +first_time(void **state) +{ + // This also tests that a NULL reason does not crash + assert_recheck(1423548000, 0, 1423548100, 1423548100, NULL); +} + +// Update recheck time if new value is earlier than the existing one +static void +earlier_time(void **state) +{ + assert_recheck(1423548000, 1423548500, 1423548200, 1423548200, "reasons"); +} + +// Do not update recheck time if new value is later than the existing one +static void +later_time(void **state) +{ + assert_recheck(1423548000, 1423548500, 1423548600, 1423548500, "reasons"); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(null_scheduler), + cmocka_unit_test(too_early), + cmocka_unit_test(first_time), + cmocka_unit_test(earlier_time), + cmocka_unit_test(later_time)) diff --git a/lib/pengine/tests/status/pe_new_working_set_test.c b/lib/common/tests/scheduler/pcmk_new_scheduler_test.c similarity index 60% rename from lib/pengine/tests/status/pe_new_working_set_test.c rename to lib/common/tests/scheduler/pcmk_new_scheduler_test.c index b385f9cd113..e7545df7620 100644 --- a/lib/pengine/tests/status/pe_new_working_set_test.c +++ b/lib/common/tests/scheduler/pcmk_new_scheduler_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2022-2023 the Pacemaker project contributors + * Copyright 2022-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -15,29 +15,30 @@ #include "mock_private.h" static void -calloc_fails(void **state) { +calloc_fails(void **state) +{ pcmk__mock_calloc = true; // calloc() will return NULL expect_value(__wrap_calloc, nmemb, 1); expect_value(__wrap_calloc, size, sizeof(pcmk_scheduler_t)); - assert_null(pe_new_working_set()); + assert_null(pcmk_new_scheduler()); pcmk__mock_calloc = false; // Use real calloc() } static void -calloc_succeeds(void **state) { - pcmk_scheduler_t *scheduler = pe_new_working_set(); +calloc_succeeds(void **state) +{ + pcmk_scheduler_t *scheduler = pcmk_new_scheduler(); - /* Nothing else to test about this function, as all it does is call - * set_working_set_defaults which is also a public function and should - * get its own unit test. + /* We only need to test that the allocated memory is non-NULL, as all the + * function does otherwise is call pcmk__set_scheduler_defaults(), which + * should have its own unit test. */ assert_non_null(scheduler); + assert_non_null(scheduler->priv); - /* Avoid calling pe_free_working_set here so we don't artificially - * inflate the coverage numbers. - */ + free(scheduler->priv); free(scheduler); } diff --git a/lib/pacemaker/pcmk_rule.c b/lib/pacemaker/pcmk_rule.c index 6eb344e6b1c..0d0fbd5abeb 100644 --- a/lib/pacemaker/pcmk_rule.c +++ b/lib/pacemaker/pcmk_rule.c @@ -185,7 +185,7 @@ pcmk__check_rules(pcmk__output_t *out, xmlNodePtr input, const crm_time_t *date, } } - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); return rc; } diff --git a/lib/pacemaker/pcmk_sched_actions.c b/lib/pacemaker/pcmk_sched_actions.c index e6ed67c0d9b..70e5f9083b7 100644 --- a/lib/pacemaker/pcmk_sched_actions.c +++ b/lib/pacemaker/pcmk_sched_actions.c @@ -1839,8 +1839,8 @@ process_rsc_history(const xmlNode *rsc_entry, pcmk_resource_t *rsc, * definition appear to have been changed. Defer the check until * later in this case. */ - pe__add_param_check(rsc_op, rsc, node, pcmk__check_active, - rsc->priv->scheduler); + pcmk__add_param_check(rsc_op, rsc, node, pcmk__check_active, + rsc->priv->scheduler); } else if (pcmk__check_action_config(rsc, node, rsc_op) && (pe_get_failcount(node, rsc, NULL, pcmk__fc_effective, diff --git a/lib/pacemaker/pcmk_sched_location.c b/lib/pacemaker/pcmk_sched_location.c index a3915b54355..fe8513dc922 100644 --- a/lib/pacemaker/pcmk_sched_location.c +++ b/lib/pacemaker/pcmk_sched_location.c @@ -383,8 +383,8 @@ unpack_rsc_location(xmlNode *xml_obj, pcmk_resource_t *rsc, if (crm_time_is_defined(next_change)) { time_t t = (time_t) crm_time_get_seconds_since_epoch(next_change); - pe__update_recheck_time(t, rsc->priv->scheduler, - "location rule evaluation"); + pcmk__update_recheck_time(t, rsc->priv->scheduler, + "location rule evaluation"); } crm_time_free(next_change); } diff --git a/lib/pacemaker/pcmk_sched_primitive.c b/lib/pacemaker/pcmk_sched_primitive.c index ad68c6b49f5..b1c112abed3 100644 --- a/lib/pacemaker/pcmk_sched_primitive.c +++ b/lib/pacemaker/pcmk_sched_primitive.c @@ -1623,7 +1623,10 @@ shutdown_time(pcmk_node_t *node) shutdown, pcmk__node_name(node), pcmk_rc_str(rc)); } } - return (result == 0)? get_effective_time(node->priv->scheduler) : result; + if (result == 0) { + result = pcmk__scheduler_epoch_time(node->priv->scheduler); + } + return result; } /*! @@ -1704,8 +1707,8 @@ pcmk__primitive_shutdown_lock(pcmk_resource_t *rsc) pcmk__rsc_info(rsc, "Locking %s to %s due to shutdown (expires @%lld)", rsc->id, pcmk__node_name(rsc->priv->lock_node), (long long) lock_expiration); - pe__update_recheck_time(++lock_expiration, scheduler, - "shutdown lock expiration"); + pcmk__update_recheck_time(++lock_expiration, scheduler, + "shutdown lock expiration"); } else { pcmk__rsc_info(rsc, "Locking %s to %s due to shutdown", rsc->id, pcmk__node_name(rsc->priv->lock_node)); diff --git a/lib/pacemaker/pcmk_scheduler.c b/lib/pacemaker/pcmk_scheduler.c index 8960c298f57..4debba82b5b 100644 --- a/lib/pacemaker/pcmk_scheduler.c +++ b/lib/pacemaker/pcmk_scheduler.c @@ -386,8 +386,8 @@ static void schedule_resource_actions(pcmk_scheduler_t *scheduler) { // Process deferred action checks - pe__foreach_param_check(scheduler, check_params); - pe__free_param_checks(scheduler); + pcmk__foreach_param_check(scheduler, check_params); + pcmk__free_param_checks(scheduler); if (pcmk_is_set(scheduler->flags, pcmk__sched_probe_resources)) { crm_trace("Scheduling probes"); @@ -743,17 +743,9 @@ unpack_cib(xmlNode *cib, unsigned long long flags, pcmk_scheduler_t *scheduler) pcmk__set_scheduler_flags(scheduler, flags); return; } - pcmk__assert(cib != NULL); crm_trace("Calculating cluster status"); - - /* This will zero the entire struct without freeing anything first, so - * callers should never call pcmk__schedule_actions() with a populated data - * set unless pcmk__sched_have_status is set (i.e. cluster_status() was - * previously called, whether directly or via pcmk__schedule_actions()). - */ - set_working_set_defaults(scheduler); - + pcmk_reset_scheduler(scheduler); pcmk__set_scheduler_flags(scheduler, flags); scheduler->input = cib; cluster_status(scheduler); // Sets pcmk__sched_have_status @@ -838,7 +830,7 @@ pcmk__init_scheduler(pcmk__output_t *out, xmlNodePtr input, const crm_time_t *da // Allows for cleaner syntax than dereferencing the scheduler argument pcmk_scheduler_t *new_scheduler = NULL; - new_scheduler = pe_new_working_set(); + new_scheduler = pcmk_new_scheduler(); if (new_scheduler == NULL) { return ENOMEM; } @@ -852,7 +844,7 @@ pcmk__init_scheduler(pcmk__output_t *out, xmlNodePtr input, const crm_time_t *da new_scheduler->input = pcmk__xml_copy(NULL, input); if (new_scheduler->input == NULL) { out->err(out, "Failed to copy input XML"); - pe_free_working_set(new_scheduler); + pcmk_free_scheduler(new_scheduler); return ENOMEM; } @@ -860,7 +852,7 @@ pcmk__init_scheduler(pcmk__output_t *out, xmlNodePtr input, const crm_time_t *da int rc = cib__signon_query(out, NULL, &(new_scheduler->input)); if (rc != pcmk_rc_ok) { - pe_free_working_set(new_scheduler); + pcmk_free_scheduler(new_scheduler); return rc; } } diff --git a/lib/pacemaker/pcmk_simulate.c b/lib/pacemaker/pcmk_simulate.c index dadf52c1e3a..d076aa88a9e 100644 --- a/lib/pacemaker/pcmk_simulate.c +++ b/lib/pacemaker/pcmk_simulate.c @@ -370,7 +370,7 @@ profile_file(const char *xml_file, long long repeat, scheduler->input = input; set_effective_date(scheduler, false, use_date); pcmk__schedule_actions(input, scheduler_flags, scheduler); - pe_reset_working_set(scheduler); + pcmk_reset_scheduler(scheduler); } end = clock(); @@ -795,7 +795,7 @@ pcmk__simulate_transition(pcmk_scheduler_t *scheduler, cib_t *cib, cib_sync_call); pcmk__assert(rc == pcmk_ok); - pe_reset_working_set(scheduler); + pcmk_reset_scheduler(scheduler); scheduler->input = cib_object; out->end_list(out); } @@ -871,7 +871,7 @@ pcmk__simulate(pcmk_scheduler_t *scheduler, pcmk__output_t *out, goto simulate_done; } - cleanup_calculations(scheduler); + pcmk_reset_scheduler(scheduler); reset(scheduler, input, out, use_date, flags); cluster_status(scheduler); } diff --git a/lib/pacemaker/pcmk_status.c b/lib/pacemaker/pcmk_status.c index 002817c06ae..e1114562795 100644 --- a/lib/pacemaker/pcmk_status.c +++ b/lib/pacemaker/pcmk_status.c @@ -102,7 +102,7 @@ pcmk__output_cluster_status(pcmk_scheduler_t *scheduler, stonith_t *stonith, fence_history); } - pe_reset_working_set(scheduler); + pcmk_reset_scheduler(scheduler); scheduler->input = cib_copy; cluster_status(scheduler); @@ -258,7 +258,7 @@ pcmk__status(pcmk__output_t *out, cib_t *cib, goto done; } - scheduler = pe_new_working_set(); + scheduler = pcmk_new_scheduler(); pcmk__mem_assert(scheduler); scheduler->priv->out = out; @@ -276,7 +276,7 @@ pcmk__status(pcmk__output_t *out, cib_t *cib, } done: - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); stonith_api_delete(stonith); pcmk__xml_free(current_cib); return pcmk_rc_ok; diff --git a/lib/pacemaker/pcmk_ticket.c b/lib/pacemaker/pcmk_ticket.c index 44b9fa56f67..6e9d2979386 100644 --- a/lib/pacemaker/pcmk_ticket.c +++ b/lib/pacemaker/pcmk_ticket.c @@ -253,7 +253,7 @@ pcmk_ticket_delete(xmlNodePtr *xml, const char *ticket_id, bool force) } pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml); - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); return rc; } @@ -307,7 +307,7 @@ pcmk_ticket_get_attr(xmlNodePtr *xml, const char *ticket_id, done: pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml); - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); return rc; } @@ -367,7 +367,7 @@ pcmk_ticket_info(xmlNodePtr *xml, const char *ticket_id) done: pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml); - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); return rc; } @@ -439,7 +439,7 @@ pcmk_ticket_remove_attr(xmlNodePtr *xml, const char *ticket_id, GList *attr_dele } pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml); - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); return rc; } @@ -508,7 +508,7 @@ pcmk_ticket_set_attr(xmlNodePtr *xml, const char *ticket_id, GHashTable *attr_se } pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml); - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); return rc; } diff --git a/lib/pacemaker/pcmk_verify.c b/lib/pacemaker/pcmk_verify.c index 893299c9ed4..77dcc5a1777 100644 --- a/lib/pacemaker/pcmk_verify.c +++ b/lib/pacemaker/pcmk_verify.c @@ -144,7 +144,7 @@ pcmk_verify(xmlNodePtr *xml, const char *cib_source) goto done; } - scheduler = pe_new_working_set(); + scheduler = pcmk_new_scheduler(); if (scheduler == NULL) { rc = errno; out->err(out, "Couldn't allocate scheduler data: %s", pcmk_rc_str(rc)); @@ -155,7 +155,7 @@ pcmk_verify(xmlNodePtr *xml, const char *cib_source) rc = pcmk__verify(scheduler, out, &cib_object); done: - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); pcmk__xml_output_finish(out, pcmk_rc2exitc(rc), xml); pcmk__xml_free(cib_object); return rc; diff --git a/lib/pengine/bundle.c b/lib/pengine/bundle.c index f19fbd11c04..8fe6ed9d47e 100644 --- a/lib/pengine/bundle.c +++ b/lib/pengine/bundle.c @@ -1264,7 +1264,7 @@ pe__unpack_bundle(pcmk_resource_t *rsc, pcmk_scheduler_t *scheduler) if (create_replica_resources(rsc, bundle_data, replica) != pcmk_rc_ok) { pcmk__config_err("Failed unpacking resource %s", rsc->id); - rsc->priv->fns->free(rsc); + pcmk__free_resource(rsc); return FALSE; } @@ -1825,17 +1825,17 @@ free_bundle_replica(pcmk__bundle_replica_t *replica) if (replica->ip) { pcmk__xml_free(replica->ip->priv->xml); replica->ip->priv->xml = NULL; - replica->ip->priv->fns->free(replica->ip); + pcmk__free_resource(replica->ip); } if (replica->container) { pcmk__xml_free(replica->container->priv->xml); replica->container->priv->xml = NULL; - replica->container->priv->fns->free(replica->container); + pcmk__free_resource(replica->container); } if (replica->remote) { pcmk__xml_free(replica->remote->priv->xml); replica->remote->priv->xml = NULL; - replica->remote->priv->fns->free(replica->remote); + pcmk__free_resource(replica->remote); } free(replica->ipaddr); free(replica); @@ -1870,7 +1870,7 @@ pe__free_bundle(pcmk_resource_t *rsc) if(bundle_data->child) { pcmk__xml_free(bundle_data->child->priv->xml); bundle_data->child->priv->xml = NULL; - bundle_data->child->priv->fns->free(bundle_data->child); + pcmk__free_resource(bundle_data->child); } common_free(rsc); } diff --git a/lib/pengine/clone.c b/lib/pengine/clone.c index 24953cd131e..2764af26fc0 100644 --- a/lib/pengine/clone.c +++ b/lib/pengine/clone.c @@ -931,7 +931,7 @@ clone_free(pcmk_resource_t * rsc) /* There could be a saved unexpanded xml */ pcmk__xml_free(child_rsc->priv->orig_xml); child_rsc->priv->orig_xml = NULL; - child_rsc->priv->fns->free(child_rsc); + pcmk__free_resource(child_rsc); } g_list_free(rsc->priv->children); diff --git a/lib/pengine/complex.c b/lib/pengine/complex.c index 93ee2659895..84b00e32c42 100644 --- a/lib/pengine/complex.c +++ b/lib/pengine/complex.c @@ -947,7 +947,7 @@ pe__unpack_resource(xmlNode *xml_obj, pcmk_resource_t **rsc, "default" : pcmk_role_text(rsc_private->next_role)); if (rsc_private->fns->unpack(*rsc, scheduler) == FALSE) { - rsc_private->fns->free(*rsc); + pcmk__free_resource(*rsc); *rsc = NULL; return pcmk_rc_unpack_error; } @@ -972,7 +972,7 @@ pe__unpack_resource(xmlNode *xml_obj, pcmk_resource_t **rsc, if (expanded_xml) { if (add_template_rsc(xml_obj, scheduler) == FALSE) { - rsc_private->fns->free(*rsc); + pcmk__free_resource(*rsc); *rsc = NULL; return pcmk_rc_unpack_error; } diff --git a/lib/pengine/failcounts.c b/lib/pengine/failcounts.c index 1288166c2ee..7d3b0de6a6b 100644 --- a/lib/pengine/failcounts.c +++ b/lib/pengine/failcounts.c @@ -398,7 +398,7 @@ pe_get_failcount(const pcmk_node_t *node, pcmk_resource_t *rsc, && (fc_data.last_failure > 0) && (rsc->priv->failure_expiration_ms > 0)) { - time_t now = get_effective_time(rsc->priv->scheduler); + time_t now = pcmk__scheduler_epoch_time(rsc->priv->scheduler); const guint expiration = pcmk__timeout_ms2s(rsc->priv->failure_expiration_ms); if (now > (fc_data.last_failure + expiration)) { diff --git a/lib/pengine/group.c b/lib/pengine/group.c index 2f3793da6c9..9d22ae1312f 100644 --- a/lib/pengine/group.c +++ b/lib/pengine/group.c @@ -391,7 +391,7 @@ group_free(pcmk_resource_t * rsc) pcmk__assert(child_rsc != NULL); pcmk__rsc_trace(child_rsc, "Freeing child %s", child_rsc->id); - child_rsc->priv->fns->free(child_rsc); + pcmk__free_resource(child_rsc); } pcmk__rsc_trace(rsc, "Freeing child list"); diff --git a/lib/pengine/pe_actions.c b/lib/pengine/pe_actions.c index 7bc65dcad1c..2cec664f7f4 100644 --- a/lib/pengine/pe_actions.c +++ b/lib/pengine/pe_actions.c @@ -168,7 +168,7 @@ pcmk__find_action_config(const pcmk_resource_t *rsc, const char *action_name, * * \return Newly allocated action * \note This function takes ownership of \p key. It is the caller's - * responsibility to free the return value with pe_free_action(). + * responsibility to free the return value using pcmk__free_action(). */ static pcmk_action_t * new_action(char *key, const char *task, pcmk_resource_t *rsc, @@ -239,7 +239,7 @@ new_action(char *key, const char *task, pcmk_resource_t *rsc, * * \param[in] action_xml XML of action's configuration in CIB (if any) * \param[in,out] node_attrs Table of node attributes (for rule evaluation) - * \param[in,out] scheduler Cluster working set (for rule evaluation) + * \param[in,out] scheduler Scheduler data (for rule evaluation) * * \return Newly allocated hash table of action-specific instance parameters */ @@ -1345,28 +1345,6 @@ pe_fence_op(pcmk_node_t *node, const char *op, bool optional, return stonith_op; } -void -pe_free_action(pcmk_action_t *action) -{ - if (action == NULL) { - return; - } - g_list_free_full(action->actions_before, free); - g_list_free_full(action->actions_after, free); - if (action->extra) { - g_hash_table_destroy(action->extra); - } - if (action->meta) { - g_hash_table_destroy(action->meta); - } - pcmk__free_node_copy(action->node); - free(action->cancel_task); - free(action->reason); - free(action->task); - free(action->uuid); - free(action); -} - enum pcmk__action_type get_complex_task(const pcmk_resource_t *rsc, const char *name) { diff --git a/lib/pengine/remote.c b/lib/pengine/remote.c index 395fa473e69..b3820a742d5 100644 --- a/lib/pengine/remote.c +++ b/lib/pengine/remote.c @@ -179,64 +179,3 @@ pe_create_remote_xml(xmlNode *parent, const char *uname, } return remote; } - -// History entry to be checked for fail count clearing -struct check_op { - const xmlNode *rsc_op; // History entry XML - pcmk_resource_t *rsc; // Known resource corresponding to history entry - pcmk_node_t *node; // Known node corresponding to history entry - enum pcmk__check_parameters check_type; // What needs checking -}; - -void -pe__add_param_check(const xmlNode *rsc_op, pcmk_resource_t *rsc, - pcmk_node_t *node, enum pcmk__check_parameters flag, - pcmk_scheduler_t *scheduler) -{ - struct check_op *check_op = NULL; - - CRM_CHECK(scheduler && rsc_op && rsc && node, return); - - check_op = pcmk__assert_alloc(1, sizeof(struct check_op)); - - crm_trace("Deferring checks of %s until after allocation", - pcmk__xe_id(rsc_op)); - check_op->rsc_op = rsc_op; - check_op->rsc = rsc; - check_op->node = node; - check_op->check_type = flag; - scheduler->priv->param_check = g_list_prepend(scheduler->priv->param_check, - check_op); -} - -/*! - * \internal - * \brief Call a function for each action to be checked for addr substitution - * - * \param[in,out] scheduler Scheduler data - * \param[in] cb Function to be called - */ -void -pe__foreach_param_check(pcmk_scheduler_t *scheduler, - void (*cb)(pcmk_resource_t*, pcmk_node_t*, - const xmlNode*, enum pcmk__check_parameters)) -{ - CRM_CHECK(scheduler && cb, return); - - for (GList *item = scheduler->priv->param_check; - item != NULL; item = item->next) { - struct check_op *check_op = item->data; - - cb(check_op->rsc, check_op->node, check_op->rsc_op, - check_op->check_type); - } -} - -void -pe__free_param_checks(pcmk_scheduler_t *scheduler) -{ - if ((scheduler != NULL) && (scheduler->priv->param_check != NULL)) { - g_list_free_full(scheduler->priv->param_check, free); - scheduler->priv->param_check = NULL; - } -} diff --git a/lib/pengine/status.c b/lib/pengine/status.c index 2e4deb07e13..beb92786e00 100644 --- a/lib/pengine/status.c +++ b/lib/pengine/status.c @@ -20,49 +20,6 @@ #include #include -/*! - * \brief Create a new object to hold scheduler data - * - * \return New, initialized scheduler data on success, else NULL (and set errno) - * \note Only pcmk_scheduler_t objects created with this function (as opposed - * to statically declared or directly allocated) should be used with the - * functions in this library, to allow for future extensions to the - * data type. The caller is responsible for freeing the memory with - * pe_free_working_set() when the instance is no longer needed. - */ -pcmk_scheduler_t * -pe_new_working_set(void) -{ - pcmk_scheduler_t *scheduler = calloc(1, sizeof(pcmk_scheduler_t)); - - if (scheduler == NULL) { - return NULL; - } - scheduler->priv = calloc(1, sizeof(pcmk__scheduler_private_t)); - if (scheduler->priv == NULL) { - free(scheduler); - return NULL; - } - set_working_set_defaults(scheduler); - return scheduler; -} - -/*! - * \brief Free scheduler data - * - * \param[in,out] scheduler Scheduler data to free - */ -void -pe_free_working_set(pcmk_scheduler_t *scheduler) -{ - if (scheduler != NULL) { - pe_reset_working_set(scheduler); - free(scheduler->priv->local_node_name); - free(scheduler->priv); - free(scheduler); - } -} - #define XPATH_DEPRECATED_RULES \ "//" PCMK_XE_OP_DEFAULTS "//" PCMK_XE_EXPRESSION \ "|//" PCMK_XE_OP "//" PCMK_XE_EXPRESSION @@ -205,135 +162,110 @@ cluster_status(pcmk_scheduler_t * scheduler) return TRUE; } -/*! - * \internal - * \brief Free a list of pcmk_resource_t - * - * \param[in,out] resources List to free - * - * \note When the scheduler's resource list is freed, that includes the original - * storage for the uname and id of any Pacemaker Remote nodes in the - * scheduler's node list, so take care not to use those afterward. - * \todo Refactor pcmk_node_t to strdup() the node name. - */ -static void -pe_free_resources(GList *resources) +pcmk_resource_t * +pe_find_resource(GList *rsc_list, const char *id) { - pcmk_resource_t *rsc = NULL; - GList *iterator = resources; + return pe_find_resource_with_flags(rsc_list, id, pcmk_rsc_match_history); +} - while (iterator != NULL) { - rsc = (pcmk_resource_t *) iterator->data; - iterator = iterator->next; - rsc->priv->fns->free(rsc); - } - if (resources != NULL) { - g_list_free(resources); +pcmk_resource_t * +pe_find_resource_with_flags(GList *rsc_list, const char *id, enum pe_find flags) +{ + GList *rIter = NULL; + + for (rIter = rsc_list; id && rIter; rIter = rIter->next) { + pcmk_resource_t *parent = rIter->data; + pcmk_resource_t *match = parent->priv->fns->find_rsc(parent, id, NULL, + flags); + + if (match != NULL) { + return match; + } } + crm_trace("No match for %s", id); + return NULL; } -static void -pe_free_actions(GList *actions) +/*! + * \brief Find a node by name or ID in a list of nodes + * + * \param[in] nodes List of nodes (as pcmk_node_t*) + * \param[in] id If not NULL, ID of node to find + * \param[in] node_name If not NULL, name of node to find + * + * \return Node from \p nodes that matches \p id if any, + * otherwise node from \p nodes that matches \p uname if any, + * otherwise NULL + */ +pcmk_node_t * +pe_find_node_any(const GList *nodes, const char *id, const char *uname) { - GList *iterator = actions; + pcmk_node_t *match = NULL; - while (iterator != NULL) { - pe_free_action(iterator->data); - iterator = iterator->next; + if (id != NULL) { + match = pe_find_node_id(nodes, id); } - if (actions != NULL) { - g_list_free(actions); + if ((match == NULL) && (uname != NULL)) { + match = pcmk__find_node_in_list(nodes, uname); } + return match; } -static void -pe_free_nodes(GList *nodes) +/*! + * \brief Find a node by ID in a list of nodes + * + * \param[in] nodes List of nodes (as pcmk_node_t*) + * \param[in] id ID of node to find + * + * \return Node from \p nodes that matches \p id if any, otherwise NULL + */ +pcmk_node_t * +pe_find_node_id(const GList *nodes, const char *id) { - for (GList *iterator = nodes; iterator != NULL; iterator = iterator->next) { - pcmk_node_t *node = (pcmk_node_t *) iterator->data; - - // Shouldn't be possible, but to be safe ... - if (node == NULL) { - continue; - } - if (node->details == NULL) { - free(node); - continue; - } + for (const GList *iter = nodes; iter != NULL; iter = iter->next) { + pcmk_node_t *node = (pcmk_node_t *) iter->data; - /* This is called after pe_free_resources(), which means that we can't - * use node->private->name for Pacemaker Remote nodes. + /* @TODO Whether node IDs should be considered case-sensitive should + * probably depend on the node type, so functionizing the comparison + * would be worthwhile */ - crm_trace("Freeing node %s", (pcmk__is_pacemaker_remote_node(node)? - "(guest or remote)" : pcmk__node_name(node))); - - if (node->priv->attrs != NULL) { - g_hash_table_destroy(node->priv->attrs); - } - if (node->priv->utilization != NULL) { - g_hash_table_destroy(node->priv->utilization); - } - if (node->priv->digest_cache != NULL) { - g_hash_table_destroy(node->priv->digest_cache); + if (pcmk__str_eq(node->priv->id, id, pcmk__str_casei)) { + return node; } - g_list_free(node->details->running_rsc); - g_list_free(node->priv->assigned_resources); - free(node->priv); - free(node->details); - free(node->assign); - free(node); - } - if (nodes != NULL) { - g_list_free(nodes); } + return NULL; } -static void -pe__free_ordering(GList *constraints) -{ - GList *iterator = constraints; - - while (iterator != NULL) { - pcmk__action_relation_t *order = iterator->data; +// Deprecated functions kept only for backward API compatibility +// LCOV_EXCL_START - iterator = iterator->next; +#include - free(order->task1); - free(order->task2); - free(order); - } - if (constraints != NULL) { - g_list_free(constraints); - } +/*! + * \brief Create a new object to hold scheduler data + * + * \return New, initialized scheduler data on success, else NULL (and set errno) + * \note Only pcmk_scheduler_t objects created with this function (as opposed + * to statically declared or directly allocated) should be used with the + * functions in this library, to allow for future extensions to the + * data type. The caller is responsible for freeing the memory with + * pcmk_free_scheduler() when the instance is no longer needed. + */ +pcmk_scheduler_t * +pe_new_working_set(void) +{ + return pcmk_new_scheduler(); } -static void -pe__free_location(GList *constraints) +void +pe_reset_working_set(pcmk_scheduler_t *scheduler) { - GList *iterator = constraints; - - while (iterator != NULL) { - pcmk__location_t *cons = iterator->data; - - iterator = iterator->next; - - g_list_free_full(cons->nodes, pcmk__free_node_copy); - free(cons->id); - free(cons); - } - if (constraints != NULL) { - g_list_free(constraints); + if (scheduler == NULL) { + return; } + pcmk_reset_scheduler(scheduler); } -/*! - * \brief Reset scheduler data to defaults without freeing it or constraints - * - * \param[in,out] scheduler Scheduler data to reset - * - * \deprecated This function is deprecated as part of the API; - * pe_reset_working_set() should be used instead. - */ void cleanup_calculations(pcmk_scheduler_t *scheduler) { @@ -363,15 +295,16 @@ cleanup_calculations(pcmk_scheduler_t *scheduler) } crm_trace("deleting resources"); - pe_free_resources(scheduler->priv->resources); + g_list_free_full(scheduler->priv->resources, pcmk__free_resource); crm_trace("deleting actions"); - pe_free_actions(scheduler->priv->actions); + g_list_free_full(scheduler->priv->actions, pcmk__free_action); crm_trace("deleting nodes"); - pe_free_nodes(scheduler->nodes); + g_list_free_full(scheduler->nodes, pcmk__free_node); + scheduler->nodes = NULL; - pe__free_param_checks(scheduler); + pcmk__free_param_checks(scheduler); g_list_free(scheduler->priv->stop_needed); crm_time_free(scheduler->priv->now); pcmk__xml_free(scheduler->input); @@ -384,36 +317,6 @@ cleanup_calculations(pcmk_scheduler_t *scheduler) && (scheduler->priv->ordering_constraints == NULL)); } -/*! - * \brief Reset scheduler data to default state without freeing it - * - * \param[in,out] scheduler Scheduler data to reset - */ -void -pe_reset_working_set(pcmk_scheduler_t *scheduler) -{ - if (scheduler == NULL) { - return; - } - - crm_trace("Deleting %d ordering constraints", - g_list_length(scheduler->priv->ordering_constraints)); - pe__free_ordering(scheduler->priv->ordering_constraints); - scheduler->priv->ordering_constraints = NULL; - - crm_trace("Deleting %d location constraints", - g_list_length(scheduler->priv->location_constraints)); - pe__free_location(scheduler->priv->location_constraints); - scheduler->priv->location_constraints = NULL; - - crm_trace("Deleting %d colocation constraints", - g_list_length(scheduler->priv->colocation_constraints)); - g_list_free_full(scheduler->priv->colocation_constraints, free); - scheduler->priv->colocation_constraints = NULL; - - cleanup_calculations(scheduler); -} - void set_working_set_defaults(pcmk_scheduler_t *scheduler) { @@ -432,110 +335,15 @@ set_working_set_defaults(pcmk_scheduler_t *scheduler) scheduler->priv->local_node_name = local_node_name; // Set defaults for everything else - scheduler->priv->next_ordering_id = 1; - scheduler->priv->next_action_id = 1; - scheduler->no_quorum_policy = pcmk_no_quorum_stop; -#if PCMK__CONCURRENT_FENCING_DEFAULT_TRUE - pcmk__set_scheduler_flags(scheduler, - pcmk__sched_symmetric_cluster - |pcmk__sched_concurrent_fencing - |pcmk__sched_stop_removed_resources - |pcmk__sched_cancel_removed_actions); -#else - pcmk__set_scheduler_flags(scheduler, - pcmk__sched_symmetric_cluster - |pcmk__sched_stop_removed_resources - |pcmk__sched_cancel_removed_actions); -#endif + pcmk__set_scheduler_defaults(scheduler); } -pcmk_resource_t * -pe_find_resource(GList *rsc_list, const char *id) -{ - return pe_find_resource_with_flags(rsc_list, id, pcmk_rsc_match_history); -} - -pcmk_resource_t * -pe_find_resource_with_flags(GList *rsc_list, const char *id, enum pe_find flags) -{ - GList *rIter = NULL; - - for (rIter = rsc_list; id && rIter; rIter = rIter->next) { - pcmk_resource_t *parent = rIter->data; - pcmk_resource_t *match = parent->priv->fns->find_rsc(parent, id, NULL, - flags); - - if (match != NULL) { - return match; - } - } - crm_trace("No match for %s", id); - return NULL; -} - -/*! - * \brief Find a node by name or ID in a list of nodes - * - * \param[in] nodes List of nodes (as pcmk_node_t*) - * \param[in] id If not NULL, ID of node to find - * \param[in] node_name If not NULL, name of node to find - * - * \return Node from \p nodes that matches \p id if any, - * otherwise node from \p nodes that matches \p uname if any, - * otherwise NULL - */ -pcmk_node_t * -pe_find_node_any(const GList *nodes, const char *id, const char *uname) -{ - pcmk_node_t *match = NULL; - - if (id != NULL) { - match = pe_find_node_id(nodes, id); - } - if ((match == NULL) && (uname != NULL)) { - match = pcmk__find_node_in_list(nodes, uname); - } - return match; -} - -/*! - * \brief Find a node by ID in a list of nodes - * - * \param[in] nodes List of nodes (as pcmk_node_t*) - * \param[in] id ID of node to find - * - * \return Node from \p nodes that matches \p id if any, otherwise NULL - */ -pcmk_node_t * -pe_find_node_id(const GList *nodes, const char *id) +void +pe_free_working_set(pcmk_scheduler_t *scheduler) { - for (const GList *iter = nodes; iter != NULL; iter = iter->next) { - pcmk_node_t *node = (pcmk_node_t *) iter->data; - - /* @TODO Whether node IDs should be considered case-sensitive should - * probably depend on the node type, so functionizing the comparison - * would be worthwhile - */ - if (pcmk__str_eq(node->priv->id, id, pcmk__str_casei)) { - return node; - } - } - return NULL; + pcmk_free_scheduler(scheduler); } -// Deprecated functions kept only for backward API compatibility -// LCOV_EXCL_START - -#include - -/*! - * \brief Find a node by name in a list of nodes - * - * \param[in] nodes List of nodes (as pcmk_node_t*) - * \param[in] node_name Name of node to find - * - * \return Node from \p nodes that matches \p node_name if any, otherwise NULL - */ pcmk_node_t * pe_find_node(const GList *nodes, const char *node_name) { diff --git a/lib/pengine/tests/native/native_find_rsc_test.c b/lib/pengine/tests/native/native_find_rsc_test.c index 676d22a88d4..070b355064c 100644 --- a/lib/pengine/tests/native/native_find_rsc_test.c +++ b/lib/pengine/tests/native/native_find_rsc_test.c @@ -37,8 +37,7 @@ setup(void **state) { return 1; } - scheduler = pe_new_working_set(); - + scheduler = pcmk_new_scheduler(); if (scheduler == NULL) { return 1; } @@ -78,8 +77,9 @@ setup(void **state) { } static int -teardown(void **state) { - pe_free_working_set(scheduler); +teardown(void **state) +{ + pcmk_free_scheduler(scheduler); pcmk__xml_cleanup(); return 0; } diff --git a/lib/pengine/tests/native/pe_base_name_eq_test.c b/lib/pengine/tests/native/pe_base_name_eq_test.c index 1a08480974b..51e4af3787b 100644 --- a/lib/pengine/tests/native/pe_base_name_eq_test.c +++ b/lib/pengine/tests/native/pe_base_name_eq_test.c @@ -36,8 +36,7 @@ setup(void **state) { return 1; } - scheduler = pe_new_working_set(); - + scheduler = pcmk_new_scheduler(); if (scheduler == NULL) { return 1; } @@ -94,8 +93,9 @@ setup(void **state) { } static int -teardown(void **state) { - pe_free_working_set(scheduler); +teardown(void **state) +{ + pcmk_free_scheduler(scheduler); pcmk__xml_cleanup(); return 0; } diff --git a/lib/pengine/tests/status/Makefile.am b/lib/pengine/tests/status/Makefile.am index e95f51a74af..79c877db59f 100644 --- a/lib/pengine/tests/status/Makefile.am +++ b/lib/pengine/tests/status/Makefile.am @@ -15,8 +15,6 @@ LDADD += $(top_builddir)/lib/pengine/libpe_status_test.la # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = pe_find_node_any_test \ - pe_find_node_id_test \ - pe_new_working_set_test \ - set_working_set_defaults_test + pe_find_node_id_test TESTS = $(check_PROGRAMS) diff --git a/lib/pengine/unpack.c b/lib/pengine/unpack.c index 1fe58ab9c2d..25857450f33 100644 --- a/lib/pengine/unpack.c +++ b/lib/pengine/unpack.c @@ -1484,7 +1484,7 @@ unpack_node_member(const xmlNode *node_state, pcmk_scheduler_t *scheduler) * avoid fencing is that effective time minus this value is less than * the pending node timeout. */ - return member? (long long) get_effective_time(scheduler) : 0LL; + return member? (long long) pcmk__scheduler_epoch_time(scheduler) : 0LL; } else { long long when_member = 0LL; @@ -1630,12 +1630,12 @@ pending_too_long(pcmk_scheduler_t *scheduler, const pcmk_node_t *node, time_t timeout = when_member + pcmk__timeout_ms2s(scheduler->priv->node_pending_ms); - if (get_effective_time(node->priv->scheduler) >= timeout) { + if (pcmk__scheduler_epoch_time(node->priv->scheduler) >= timeout) { return true; // Node has timed out } // Node is pending, but still has time - pe__update_recheck_time(timeout, scheduler, "pending node timeout"); + pcmk__update_recheck_time(timeout, scheduler, "pending node timeout"); } return false; } @@ -2682,7 +2682,7 @@ unpack_shutdown_lock(const xmlNode *rsc_entry, pcmk_resource_t *rsc, &lock_time) == pcmk_ok) && (lock_time != 0)) { if ((scheduler->priv->shutdown_lock_ms > 0U) - && (get_effective_time(scheduler) + && (pcmk__scheduler_epoch_time(scheduler) > (lock_time + pcmk__timeout_ms2s(scheduler->priv->shutdown_lock_ms)))) { pcmk__rsc_info(rsc, "Shutdown lock for %s on %s expired", rsc->id, pcmk__node_name(node)); @@ -4023,8 +4023,8 @@ should_clear_for_param_change(const xmlNode *xml_op, const char *task, * substitute addr parameters for the REMOTE_CONTAINER_HACK. * When that's needed, defer the check until later. */ - pe__add_param_check(xml_op, rsc, node, pcmk__check_last_failure, - rsc->priv->scheduler); + pcmk__add_param_check(xml_op, rsc, node, pcmk__check_last_failure, + rsc->priv->scheduler); } else { pcmk__op_digest_t *digest_data = NULL; @@ -4154,7 +4154,7 @@ check_operation_expiry(struct action_history *history) * timestamp */ - time_t now = get_effective_time(scheduler); + time_t now = pcmk__scheduler_epoch_time(scheduler); time_t last_failure = 0; // Is this particular operation history older than the failure timeout? @@ -4180,8 +4180,8 @@ check_operation_expiry(struct action_history *history) (long long) last_failure); last_failure += expiration_sec + 1; if (unexpired_fail_count && (now < last_failure)) { - pe__update_recheck_time(last_failure, scheduler, - "fail count expiration"); + pcmk__update_recheck_time(last_failure, scheduler, + "fail count expiration"); } } diff --git a/lib/pengine/utils.c b/lib/pengine/utils.c index f6c25ced2f7..c44e7c00de2 100644 --- a/lib/pengine/utils.c +++ b/lib/pengine/utils.c @@ -397,21 +397,6 @@ resource_location(pcmk_resource_t *rsc, const pcmk_node_t *node, int score, } } -time_t -get_effective_time(pcmk_scheduler_t *scheduler) -{ - if(scheduler) { - if (scheduler->priv->now == NULL) { - crm_trace("Recording a new 'now'"); - scheduler->priv->now = crm_time_new(NULL); - } - return crm_time_get_seconds_since_epoch(scheduler->priv->now); - } - - crm_trace("Defaulting to 'now'"); - return time(NULL); -} - gboolean get_target_role(const pcmk_resource_t *rsc, enum rsc_role_e *role) { @@ -662,27 +647,6 @@ pe__shutdown_requested(const pcmk_node_t *node) return !pcmk__str_eq(shutdown, "0", pcmk__str_null_matches); } -/*! - * \internal - * \brief Update "recheck by" time in scheduler data - * - * \param[in] recheck Epoch time when recheck should happen - * \param[in,out] scheduler Scheduler data - * \param[in] reason What time is being updated for (for logs) - */ -void -pe__update_recheck_time(time_t recheck, pcmk_scheduler_t *scheduler, - const char *reason) -{ - if ((recheck > get_effective_time(scheduler)) - && ((scheduler->priv->recheck_by == 0) - || (scheduler->priv->recheck_by > recheck))) { - scheduler->priv->recheck_by = recheck; - crm_debug("Updated next scheduler recheck to %s for %s", - pcmk__trim(ctime(&recheck)), reason); - } -} - /*! * \internal * \brief Extract nvpair blocks contained by a CIB XML element into a hash table @@ -721,7 +685,7 @@ pe__unpack_dataset_nvpairs(const xmlNode *xml_obj, const char *set_name, if (crm_time_is_defined(next_change)) { time_t recheck = (time_t) crm_time_get_seconds_since_epoch(next_change); - pe__update_recheck_time(recheck, scheduler, "rule evaluation"); + pcmk__update_recheck_time(recheck, scheduler, "rule evaluation"); } crm_time_free(next_change); } diff --git a/tools/crm_mon.c b/tools/crm_mon.c index 149ff7737e0..5f104d61925 100644 --- a/tools/crm_mon.c +++ b/tools/crm_mon.c @@ -1599,7 +1599,7 @@ main(int argc, char **argv) one_shot(); } - scheduler = pe_new_working_set(); + scheduler = pcmk_new_scheduler(); pcmk__mem_assert(scheduler); scheduler->priv->out = out; if ((cib->variant == cib_native) && pcmk_is_set(show, pcmk_section_times)) { @@ -2127,7 +2127,7 @@ clean_up(crm_exit_t exit_code) g_strfreev(processed_args); - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); /* (2) If this is abnormal termination and we're in curses mode, shut down * curses first. Any messages displayed to the screen before curses is shut diff --git a/tools/crm_resource.c b/tools/crm_resource.c index 5f177799e22..0e425ddbf19 100644 --- a/tools/crm_resource.c +++ b/tools/crm_resource.c @@ -170,7 +170,7 @@ bye(crm_exit_t ec) mainloop = NULL; } - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); scheduler = NULL; crm_exit(ec); return ec; @@ -981,7 +981,7 @@ initialize_scheduler_data(xmlNode **cib_xml_orig) { int rc = pcmk_rc_ok; - scheduler = pe_new_working_set(); + scheduler = pcmk_new_scheduler(); if (scheduler == NULL) { return ENOMEM; } diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c index 0c1384ddf48..ddd780f04cf 100644 --- a/tools/crm_resource_runtime.c +++ b/tools/crm_resource_runtime.c @@ -1435,7 +1435,7 @@ update_dataset(cib_t *cib, pcmk_scheduler_t *scheduler, xmlNode **cib_xml_orig, pcmk__output_t *out = scheduler->priv->out; - pe_reset_working_set(scheduler); + pcmk_reset_scheduler(scheduler); pcmk__set_scheduler_flags(scheduler, pcmk__sched_no_counts); if(simulate) { @@ -1730,7 +1730,7 @@ cli_resource_restart(pcmk__output_t *out, pcmk_resource_t *rsc, - Allow a --no-deps option (aka. --force-restart) */ - scheduler = pe_new_working_set(); + scheduler = pcmk_new_scheduler(); if (scheduler == NULL) { rc = errno; out->err(out, "Could not allocate scheduler data: %s", pcmk_rc_str(rc)); @@ -1967,7 +1967,7 @@ cli_resource_restart(pcmk__output_t *out, pcmk_resource_t *rsc, } free(rsc_id); free(lookup_id); - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); return rc; } @@ -2067,7 +2067,7 @@ wait_till_stable(pcmk__output_t *out, guint timeout_ms, cib_t * cib) expire_time += pcmk__timeout_ms2s(timeout_ms + 999); } - scheduler = pe_new_working_set(); + scheduler = pcmk_new_scheduler(); if (scheduler == NULL) { return ENOMEM; } @@ -2096,7 +2096,7 @@ wait_till_stable(pcmk__output_t *out, guint timeout_ms, cib_t * cib) } /* Get latest transition graph */ - pe_reset_working_set(scheduler); + pcmk_reset_scheduler(scheduler); rc = update_scheduler_input(out, scheduler, cib, NULL); if (rc != pcmk_rc_ok) { break; @@ -2130,7 +2130,7 @@ wait_till_stable(pcmk__output_t *out, guint timeout_ms, cib_t * cib) } while (actions_are_pending(scheduler->priv->actions) || pending_unknown_state_resources); - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); free(xpath); return rc; } diff --git a/tools/crm_simulate.c b/tools/crm_simulate.c index df5359cb4f2..8dc8b0b670e 100644 --- a/tools/crm_simulate.c +++ b/tools/crm_simulate.c @@ -510,7 +510,7 @@ main(int argc, char **argv) options.flags |= pcmk_sim_verbose; } - scheduler = pe_new_working_set(); + scheduler = pcmk_new_scheduler(); if (scheduler == NULL) { rc = ENOMEM; g_set_error(&error, PCMK__RC_ERROR, rc, @@ -561,7 +561,7 @@ main(int argc, char **argv) g_strfreev(processed_args); if (scheduler != NULL) { - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); } fflush(stderr); diff --git a/tools/crm_ticket.c b/tools/crm_ticket.c index 4a2e904344b..251ed8449fc 100644 --- a/tools/crm_ticket.c +++ b/tools/crm_ticket.c @@ -386,7 +386,7 @@ main(int argc, char **argv) goto done; } - scheduler = pe_new_working_set(); + scheduler = pcmk_new_scheduler(); if (scheduler == NULL) { rc = errno; exit_code = pcmk_rc2exitc(rc); @@ -638,7 +638,7 @@ main(int argc, char **argv) } attr_delete = NULL; - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); scheduler = NULL; cib__clean_up_connection(&cib_conn); diff --git a/tools/crm_verify.c b/tools/crm_verify.c index c491bde365b..3dd9763c0a8 100644 --- a/tools/crm_verify.c +++ b/tools/crm_verify.c @@ -243,8 +243,7 @@ main(int argc, char **argv) pcmk__xml_write_file(cib_object, options.cib_save, false); } - scheduler = pe_new_working_set(); - + scheduler = pcmk_new_scheduler(); if (scheduler == NULL) { rc = errno; g_set_error(&error, PCMK__RC_ERROR, rc, @@ -271,7 +270,7 @@ main(int argc, char **argv) out->err(out, "Configuration invalid%s%s", failure_type, verbose_hint); } - pe_free_working_set(scheduler); + pcmk_free_scheduler(scheduler); done: g_strfreev(processed_args);