root/daemons/attrd/attrd_attributes.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. attrd_create_attribute
  2. attrd_update_dampening
  3. attrd_add_value_xml
  4. attrd_clear_value_seen
  5. attrd_populate_attribute

   1 /*
   2  * Copyright 2013-2022 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 General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <errno.h>
  13 #include <stdbool.h>
  14 #include <stdlib.h>
  15 #include <glib.h>
  16 
  17 #include <crm/msg_xml.h>
  18 #include <crm/common/logging.h>
  19 #include <crm/common/results.h>
  20 #include <crm/common/strings_internal.h>
  21 #include <crm/common/xml.h>
  22 
  23 #include "pacemaker-attrd.h"
  24 
  25 static attribute_t *
  26 attrd_create_attribute(xmlNode *xml)
     /* [previous][next][first][last][top][bottom][index][help] */
  27 {
  28     int dampen = 0;
  29     const char *value = crm_element_value(xml, PCMK__XA_ATTR_DAMPENING);
  30     attribute_t *a = calloc(1, sizeof(attribute_t));
  31 
  32     CRM_ASSERT(a != NULL);
  33 
  34     a->id      = crm_element_value_copy(xml, PCMK__XA_ATTR_NAME);
  35     a->set     = crm_element_value_copy(xml, PCMK__XA_ATTR_SET);
  36     a->uuid    = crm_element_value_copy(xml, PCMK__XA_ATTR_UUID);
  37     a->values = pcmk__strikey_table(NULL, attrd_free_attribute_value);
  38 
  39     crm_element_value_int(xml, PCMK__XA_ATTR_IS_PRIVATE, &a->is_private);
  40 
  41     a->user = crm_element_value_copy(xml, PCMK__XA_ATTR_USER);
  42     crm_trace("Performing all %s operations as user '%s'", a->id, a->user);
  43 
  44     if (value != NULL) {
  45         dampen = crm_get_msec(value);
  46     }
  47     crm_trace("Created attribute %s with %s write delay", a->id,
  48               (a->timeout_ms == 0)? "no" : pcmk__readable_interval(a->timeout_ms));
  49 
  50     if(dampen > 0) {
  51         a->timeout_ms = dampen;
  52         a->timer = attrd_add_timer(a->id, a->timeout_ms, a);
  53     } else if (dampen < 0) {
  54         crm_warn("Ignoring invalid delay %s for attribute %s", value, a->id);
  55     }
  56 
  57     g_hash_table_replace(attributes, a->id, a);
  58     return a;
  59 }
  60 
  61 static int
  62 attrd_update_dampening(attribute_t *a, xmlNode *xml, const char *attr)
     /* [previous][next][first][last][top][bottom][index][help] */
  63 {
  64     const char *dvalue = crm_element_value(xml, PCMK__XA_ATTR_DAMPENING);
  65     int dampen = 0;
  66 
  67     if (dvalue == NULL) {
  68         crm_warn("Could not update %s: peer did not specify value for delay",
  69                  attr);
  70         return EINVAL;
  71     }
  72 
  73     dampen = crm_get_msec(dvalue);
  74     if (dampen < 0) {
  75         crm_warn("Could not update %s: invalid delay value %dms (%s)",
  76                  attr, dampen, dvalue);
  77         return EINVAL;
  78     }
  79 
  80     if (a->timeout_ms != dampen) {
  81         mainloop_timer_del(a->timer);
  82         a->timeout_ms = dampen;
  83         if (dampen > 0) {
  84             a->timer = attrd_add_timer(attr, a->timeout_ms, a);
  85             crm_info("Update attribute %s delay to %dms (%s)",
  86                      attr, dampen, dvalue);
  87         } else {
  88             a->timer = NULL;
  89             crm_info("Update attribute %s to remove delay", attr);
  90         }
  91 
  92         /* If dampening changed, do an immediate write-out,
  93          * otherwise repeated dampening changes would prevent write-outs
  94          */
  95         attrd_write_or_elect_attribute(a);
  96     }
  97 
  98     return pcmk_rc_ok;
  99 }
 100 
 101 GHashTable *attributes = NULL;
 102 
 103 /*!
 104  * \internal
 105  * \brief Create an XML representation of an attribute for use in peer messages
 106  *
 107  * \param[in,out] parent      Create attribute XML as child element of this
 108  * \param[in]     a           Attribute to represent
 109  * \param[in]     v           Attribute value to represent
 110  * \param[in]     force_write If true, value should be written even if unchanged
 111  *
 112  * \return XML representation of attribute
 113  */
 114 xmlNode *
 115 attrd_add_value_xml(xmlNode *parent, const attribute_t *a,
     /* [previous][next][first][last][top][bottom][index][help] */
 116                     const attribute_value_t *v, bool force_write)
 117 {
 118     xmlNode *xml = create_xml_node(parent, __func__);
 119 
 120     crm_xml_add(xml, PCMK__XA_ATTR_NAME, a->id);
 121     crm_xml_add(xml, PCMK__XA_ATTR_SET, a->set);
 122     crm_xml_add(xml, PCMK__XA_ATTR_UUID, a->uuid);
 123     crm_xml_add(xml, PCMK__XA_ATTR_USER, a->user);
 124     pcmk__xe_add_node(xml, v->nodename, v->nodeid);
 125     if (v->is_remote != 0) {
 126         crm_xml_add_int(xml, PCMK__XA_ATTR_IS_REMOTE, 1);
 127     }
 128     crm_xml_add(xml, PCMK__XA_ATTR_VALUE, v->current);
 129     crm_xml_add_int(xml, PCMK__XA_ATTR_DAMPENING, a->timeout_ms / 1000);
 130     crm_xml_add_int(xml, PCMK__XA_ATTR_IS_PRIVATE, a->is_private);
 131     crm_xml_add_int(xml, PCMK__XA_ATTR_FORCE, force_write);
 132 
 133     return xml;
 134 }
 135 
 136 void
 137 attrd_clear_value_seen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 138 {
 139     GHashTableIter aIter;
 140     GHashTableIter vIter;
 141     attribute_t *a;
 142     attribute_value_t *v = NULL;
 143 
 144     g_hash_table_iter_init(&aIter, attributes);
 145     while (g_hash_table_iter_next(&aIter, NULL, (gpointer *) & a)) {
 146         g_hash_table_iter_init(&vIter, a->values);
 147         while (g_hash_table_iter_next(&vIter, NULL, (gpointer *) & v)) {
 148             v->seen = FALSE;
 149             crm_trace("Clear seen flag %s[%s] = %s.", a->id, v->nodename, v->current);
 150         }
 151     }
 152 }
 153 
 154 attribute_t *
 155 attrd_populate_attribute(xmlNode *xml, const char *attr)
     /* [previous][next][first][last][top][bottom][index][help] */
 156 {
 157     attribute_t *a = NULL;
 158     bool update_both = false;
 159 
 160     const char *op = crm_element_value(xml, PCMK__XA_TASK);
 161 
 162     // NULL because PCMK__ATTRD_CMD_SYNC_RESPONSE has no PCMK__XA_TASK
 163     update_both = pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE_BOTH,
 164                                pcmk__str_null_matches);
 165 
 166     // Look up or create attribute entry
 167     a = g_hash_table_lookup(attributes, attr);
 168     if (a == NULL) {
 169         if (update_both || pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE, pcmk__str_none)) {
 170             a = attrd_create_attribute(xml);
 171         } else {
 172             crm_warn("Could not update %s: attribute not found", attr);
 173             return NULL;
 174         }
 175     }
 176 
 177     // Update attribute dampening
 178     if (update_both || pcmk__str_eq(op, PCMK__ATTRD_CMD_UPDATE_DELAY, pcmk__str_none)) {
 179         int rc = attrd_update_dampening(a, xml, attr);
 180 
 181         if (rc != pcmk_rc_ok || !update_both) {
 182             return NULL;
 183         }
 184     }
 185 
 186     return a;
 187 }

/* [previous][next][first][last][top][bottom][index][help] */