LCOV - code coverage report
Current view: top level - pacemaker - pcmk_graph_logging.c (source / functions) Hit Total Coverage
Test: Pacemaker code coverage Lines: 0 93 0.0 %
Date: 2024-05-07 11:09:47 Functions: 0 10 0.0 %

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

Generated by: LCOV version 1.14