root/lib/pacemaker/pcmk_graph_logging.c

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

DEFINITIONS

This source file includes following definitions.
  1. pcmk__graph_status2text
  2. actiontype2text
  3. find_graph_action_by_id
  4. synapse_state_str
  5. synapse_pending_inputs
  6. log_unresolved_inputs
  7. log_synapse_action
  8. log_synapse
  9. pcmk__log_graph_action
  10. pcmk__log_graph

   1 /*
   2  * Copyright 2004-2023 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU Lesser General Public License
   7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <crm/crm.h>
  13 #include <crm/msg_xml.h>
  14 #include <crm/common/xml.h>
  15 #include <pacemaker-internal.h>
  16 
  17 /*!
  18  * \internal
  19  * \brief Return text equivalent of an enum pcmk__graph_status for logging
  20  *
  21  * \param[in] state  Transition status
  22  *
  23  * \return Human-readable text equivalent of \p state
  24  */
  25 const char *
  26 pcmk__graph_status2text(enum pcmk__graph_status state)
     /* [previous][next][first][last][top][bottom][index][help] */
  27 {
  28     switch (state) {
  29         case pcmk__graph_active:
  30             return "active";
  31         case pcmk__graph_pending:
  32             return "pending";
  33         case pcmk__graph_complete:
  34             return "complete";
  35         case pcmk__graph_terminated:
  36             return "terminated";
  37     }
  38     return "unknown";
  39 }
  40 
  41 static const char *
  42 actiontype2text(enum pcmk__graph_action_type type)
     /* [previous][next][first][last][top][bottom][index][help] */
  43 {
  44     switch (type) {
  45         case pcmk__pseudo_graph_action:
  46             return "pseudo";
  47         case pcmk__rsc_graph_action:
  48             return "resource";
  49         case pcmk__cluster_graph_action:
  50             return "cluster";
  51     }
  52     return "invalid";
  53 }
  54 
  55 /*!
  56  * \internal
  57  * \brief Find a transition graph action by ID
  58  *
  59  * \param[in] graph  Transition graph to search
  60  * \param[in] id     Action ID to search for
  61  *
  62  * \return Transition graph action corresponding to \p id, or NULL if none
  63  */
  64 static const pcmk__graph_action_t *
  65 find_graph_action_by_id(const pcmk__graph_t *graph, int id)
     /* [previous][next][first][last][top][bottom][index][help] */
  66 {
  67     if (graph == NULL) {
  68         return NULL;
  69     }
  70 
  71     for (const GList *sIter = graph->synapses; sIter != NULL;
  72          sIter = sIter->next) {
  73 
  74         const pcmk__graph_synapse_t *synapse = NULL;
  75 
  76         synapse = (const pcmk__graph_synapse_t *) sIter->data;
  77         for (const GList *aIter = synapse->actions; aIter != NULL;
  78              aIter = aIter->next) {
  79 
  80             const pcmk__graph_action_t *action = NULL;
  81 
  82             action = (const pcmk__graph_action_t *) aIter->data;
  83             if (action->id == id) {
  84                 return action;
  85             }
  86         }
  87     }
  88     return NULL;
  89 }
  90 
  91 static const char *
  92 synapse_state_str(pcmk__graph_synapse_t *synapse)
     /* [previous][next][first][last][top][bottom][index][help] */
  93 {
  94     if (pcmk_is_set(synapse->flags, pcmk__synapse_failed)) {
  95         return "Failed";
  96 
  97     } else if (pcmk_is_set(synapse->flags, pcmk__synapse_confirmed)) {
  98         return "Completed";
  99 
 100     } else if (pcmk_is_set(synapse->flags, pcmk__synapse_executed)) {
 101         return "In-flight";
 102 
 103     } else if (pcmk_is_set(synapse->flags, pcmk__synapse_ready)) {
 104         return "Ready";
 105     }
 106     return "Pending";
 107 }
 108 
 109 /*!
 110  * \internal
 111  * \brief List the action IDs of pending inputs to a transition graph synapse
 112  *
 113  * \param[in] graph    Transition graph to which \p synapse belongs
 114  * \param[in] synapse  Synapse whose inputs to check
 115  *
 116  * \return A \p GString containing the space-delimited action IDs of inputs to
 117  *         \p synapse that haven't completed successfully
 118  *
 119  * \note The caller is responsible for freeing the return value using
 120  *       \p g_string_free().
 121  */
 122 static GString *
 123 synapse_pending_inputs(const pcmk__graph_t *graph,
     /* [previous][next][first][last][top][bottom][index][help] */
 124                        const pcmk__graph_synapse_t *synapse)
 125 {
 126     GString *pending = NULL;
 127 
 128     for (const GList *lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
 129         const pcmk__graph_action_t *input = (pcmk__graph_action_t *) lpc->data;
 130 
 131         if (pcmk_is_set(input->flags, pcmk__graph_action_failed)) {
 132             pcmk__add_word(&pending, 1024, ID(input->xml));
 133 
 134         } else if (pcmk_is_set(input->flags, pcmk__graph_action_confirmed)) {
 135             // Confirmed successful inputs are not pending
 136 
 137         } else if (find_graph_action_by_id(graph, input->id) != NULL) {
 138             // In-flight or pending
 139             pcmk__add_word(&pending, 1024, ID(input->xml));
 140         }
 141     }
 142     return pending;
 143 }
 144 
 145 // Log synapse inputs that aren't in graph
 146 static void
 147 log_unresolved_inputs(unsigned int log_level, pcmk__graph_t *graph,
     /* [previous][next][first][last][top][bottom][index][help] */
 148                       pcmk__graph_synapse_t *synapse)
 149 {
 150     for (GList *lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
 151         pcmk__graph_action_t *input = (pcmk__graph_action_t *) lpc->data;
 152         const char *key = crm_element_value(input->xml, XML_LRM_ATTR_TASK_KEY);
 153         const char *host = crm_element_value(input->xml, XML_LRM_ATTR_TARGET);
 154 
 155         if (find_graph_action_by_id(graph, input->id) == NULL) {
 156             do_crm_log(log_level,
 157                        " * [Input %2d]: Unresolved dependency %s op %s%s%s",
 158                        input->id, actiontype2text(input->type), key,
 159                        (host? " on " : ""), (host? host : ""));
 160         }
 161     }
 162 }
 163 
 164 static void
 165 log_synapse_action(unsigned int log_level, pcmk__graph_synapse_t *synapse,
     /* [previous][next][first][last][top][bottom][index][help] */
 166                    pcmk__graph_action_t *action, const char *pending_inputs)
 167 {
 168     const char *key = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY);
 169     const char *host = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
 170     char *desc = crm_strdup_printf("%s %s op %s",
 171                                    synapse_state_str(synapse),
 172                                    actiontype2text(action->type), key);
 173 
 174     do_crm_log(log_level,
 175                "[Action %4d]: %-50s%s%s (priority: %d, waiting: %s)",
 176                action->id, desc, (host? " on " : ""), (host? host : ""),
 177                synapse->priority, pending_inputs);
 178     free(desc);
 179 }
 180 
 181 static void
 182 log_synapse(unsigned int log_level, pcmk__graph_t *graph,
     /* [previous][next][first][last][top][bottom][index][help] */
 183             pcmk__graph_synapse_t *synapse)
 184 {
 185     GString *g_pending = NULL;
 186     const char *pending = "none";
 187 
 188     if (!pcmk_is_set(synapse->flags, pcmk__synapse_executed)) {
 189         g_pending = synapse_pending_inputs(graph, synapse);
 190 
 191         if (g_pending != NULL) {
 192             pending = (const char *) g_pending->str;
 193         }
 194     }
 195 
 196     for (GList *lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
 197         log_synapse_action(log_level, synapse,
 198                            (pcmk__graph_action_t *) lpc->data, pending);
 199     }
 200 
 201     if (g_pending != NULL) {
 202         g_string_free(g_pending, TRUE);
 203     }
 204 
 205     if (!pcmk_is_set(synapse->flags, pcmk__synapse_executed)) {
 206         log_unresolved_inputs(log_level, graph, synapse);
 207     }
 208 }
 209 
 210 void
 211 pcmk__log_graph_action(int log_level, pcmk__graph_action_t *action)
     /* [previous][next][first][last][top][bottom][index][help] */
 212 {
 213     log_synapse(log_level, NULL, action->synapse);
 214 }
 215 
 216 void
 217 pcmk__log_graph(unsigned int log_level, pcmk__graph_t *graph)
     /* [previous][next][first][last][top][bottom][index][help] */
 218 {
 219     if ((graph == NULL) || (graph->num_actions == 0)) {
 220         if (log_level == LOG_TRACE) {
 221             crm_debug("Empty transition graph");
 222         }
 223         return;
 224     }
 225 
 226     do_crm_log(log_level, "Graph %d with %d actions:"
 227                " batch-limit=%d jobs, network-delay=%ums",
 228                graph->id, graph->num_actions,
 229                graph->batch_limit, graph->network_delay);
 230 
 231     for (GList *lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
 232         log_synapse(log_level, graph, (pcmk__graph_synapse_t *) lpc->data);
 233     }
 234 }

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