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

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