summaryrefslogtreecommitdiffstats
path: root/daemons/attrd/attrd_attributes.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 06:53:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 06:53:20 +0000
commite5a812082ae033afb1eed82c0f2df3d0f6bdc93f (patch)
treea6716c9275b4b413f6c9194798b34b91affb3cc7 /daemons/attrd/attrd_attributes.c
parentInitial commit. (diff)
downloadpacemaker-e5a812082ae033afb1eed82c0f2df3d0f6bdc93f.tar.xz
pacemaker-e5a812082ae033afb1eed82c0f2df3d0f6bdc93f.zip
Adding upstream version 2.1.6.upstream/2.1.6
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'daemons/attrd/attrd_attributes.c')
-rw-r--r--daemons/attrd/attrd_attributes.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/daemons/attrd/attrd_attributes.c b/daemons/attrd/attrd_attributes.c
new file mode 100644
index 0000000..516ced7
--- /dev/null
+++ b/daemons/attrd/attrd_attributes.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2013-2022 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 <crm_internal.h>
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <glib.h>
+
+#include <crm/msg_xml.h>
+#include <crm/common/logging.h>
+#include <crm/common/results.h>
+#include <crm/common/strings_internal.h>
+#include <crm/common/xml.h>
+
+#include "pacemaker-attrd.h"
+
+static attribute_t *
+attrd_create_attribute(xmlNode *xml)
+{
+ int dampen = 0;
+ const char *value = crm_element_value(xml, PCMK__XA_ATTR_DAMPENING);
+ attribute_t *a = calloc(1, sizeof(attribute_t));
+
+ CRM_ASSERT(a != NULL);
+
+ a->id = crm_element_value_copy(xml, PCMK__XA_ATTR_NAME);
+ a->set_id = crm_element_value_copy(xml, PCMK__XA_ATTR_SET);
+ a->set_type = crm_element_value_copy(xml, PCMK__XA_ATTR_SET_TYPE);
+ a->uuid = crm_element_value_copy(xml, PCMK__XA_ATTR_UUID);
+ a->values = pcmk__strikey_table(NULL, attrd_free_attribute_value);
+
+ crm_element_value_int(xml, PCMK__XA_ATTR_IS_PRIVATE, &a->is_private);
+
+ a->user = crm_element_value_copy(xml, PCMK__XA_ATTR_USER);
+ crm_trace("Performing all %s operations as user '%s'", a->id, a->user);
+
+ if (value != NULL) {
+ dampen = crm_get_msec(value);
+ }
+ crm_trace("Created attribute %s with %s write delay", a->id,
+ (a->timeout_ms == 0)? "no" : pcmk__readable_interval(a->timeout_ms));
+
+ if(dampen > 0) {
+ a->timeout_ms = dampen;
+ a->timer = attrd_add_timer(a->id, a->timeout_ms, a);
+ } else if (dampen < 0) {
+ crm_warn("Ignoring invalid delay %s for attribute %s", value, a->id);
+ }
+
+ g_hash_table_replace(attributes, a->id, a);
+ return a;
+}
+
+static int
+attrd_update_dampening(attribute_t *a, xmlNode *xml, const char *attr)
+{
+ const char *dvalue = crm_element_value(xml, PCMK__XA_ATTR_DAMPENING);
+ int dampen = 0;
+
+ if (dvalue == NULL) {
+ crm_warn("Could not update %s: peer did not specify value for delay",
+ attr);
+ return EINVAL;
+ }
+
+ dampen = crm_get_msec(dvalue);
+ if (dampen < 0) {
+ crm_warn("Could not update %s: invalid delay value %dms (%s)",
+ attr, dampen, dvalue);
+ return EINVAL;
+ }
+
+ if (a->timeout_ms != dampen) {
+ mainloop_timer_del(a->timer);
+ a->timeout_ms = dampen;
+ if (dampen > 0) {
+ a->timer = attrd_add_timer(attr, a->timeout_ms, a);
+ crm_info("Update attribute %s delay to %dms (%s)",
+ attr, dampen, dvalue);
+ } else {
+ a->timer = NULL;
+ crm_info("Update attribute %s to remove delay", attr);
+ }
+
+ /* If dampening changed, do an immediate write-out,
+ * otherwise repeated dampening changes would prevent write-outs
+ */
+ attrd_write_or_elect_attribute(a);
+ }
+
+ return pcmk_rc_ok;
+}
+
+GHashTable *attributes = NULL;
+
+/*!
+ * \internal
+ * \brief Create an XML representation of an attribute for use in peer messages
+ *
+ * \param[in,out] parent Create attribute XML as child element of this
+ * \param[in] a Attribute to represent
+ * \param[in] v Attribute value to represent
+ * \param[in] force_write If true, value should be written even if unchanged
+ *
+ * \return XML representation of attribute
+ */
+xmlNode *
+attrd_add_value_xml(xmlNode *parent, const attribute_t *a,
+ const attribute_value_t *v, bool force_write)
+{
+ xmlNode *xml = create_xml_node(parent, __func__);
+
+ crm_xml_add(xml, PCMK__XA_ATTR_NAME, a->id);
+ crm_xml_add(xml, PCMK__XA_ATTR_SET, a->set_id);
+ crm_xml_add(xml, PCMK__XA_ATTR_UUID, a->uuid);
+ crm_xml_add(xml, PCMK__XA_ATTR_USER, a->user);
+ pcmk__xe_add_node(xml, v->nodename, v->nodeid);
+ if (v->is_remote != 0) {
+ crm_xml_add_int(xml, PCMK__XA_ATTR_IS_REMOTE, 1);
+ }
+ crm_xml_add(xml, PCMK__XA_ATTR_VALUE, v->current);
+ crm_xml_add_int(xml, PCMK__XA_ATTR_DAMPENING, a->timeout_ms / 1000);
+ crm_xml_add_int(xml, PCMK__XA_ATTR_IS_PRIVATE, a->is_private);
+ crm_xml_add_int(xml, PCMK__XA_ATTR_FORCE, force_write);
+
+ return xml;
+}
+
+void
+attrd_clear_value_seen(void)
+{
+ GHashTableIter aIter;
+ GHashTableIter vIter;
+ attribute_t *a;
+ attribute_value_t *v = NULL;
+
+ g_hash_table_iter_init(&aIter, attributes);
+ while (g_hash_table_iter_next(&aIter, NULL, (gpointer *) & a)) {
+ g_hash_table_iter_init(&vIter, a->values);
+ while (g_hash_table_iter_next(&vIter, NULL, (gpointer *) & v)) {
+ v->seen = FALSE;
+ crm_trace("Clear seen flag %s[%s] = %s.", a->id, v->nodename, v->current);
+ }
+ }
+}
+
+attribute_t *
+attrd_populate_attribute(xmlNode *xml, const char *attr)
+{
+ attribute_t *a = NULL;
+ bool update_both = false;
+
+ const char *op = crm_element_value(xml, PCMK__XA_TASK);
+
+ // NULL because PCMK__ATTRD_CMD_SYNC_RESPONSE has no PCMK__XA_TASK
+ update_both = pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE_BOTH,
+ pcmk__str_null_matches);
+
+ // Look up or create attribute entry
+ a = g_hash_table_lookup(attributes, attr);
+ if (a == NULL) {
+ if (update_both || pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE, pcmk__str_none)) {
+ a = attrd_create_attribute(xml);
+ } else {
+ crm_warn("Could not update %s: attribute not found", attr);
+ return NULL;
+ }
+ }
+
+ // Update attribute dampening
+ if (update_both || pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE_DELAY, pcmk__str_none)) {
+ int rc = attrd_update_dampening(a, xml, attr);
+
+ if (rc != pcmk_rc_ok || !update_both) {
+ return NULL;
+ }
+ }
+
+ return a;
+}