pacemaker  2.1.9-49aab99839
Scalable High-Availability cluster resource manager
pcmk_graph_logging.c
Go to the documentation of this file.
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 
24 const char *
26 {
27  switch (state) {
28  case pcmk__graph_active:
29  return "active";
31  return "pending";
33  return "complete";
35  return "terminated";
36  }
37  return "unknown";
38 }
39 
40 static const char *
41 actiontype2text(enum pcmk__graph_action_type type)
42 {
43  switch (type) {
45  return "pseudo";
47  return "resource";
49  return "cluster";
50  }
51  return "invalid";
52 }
53 
63 static const pcmk__graph_action_t *
64 find_graph_action_by_id(const pcmk__graph_t *graph, int id)
65 {
66  if (graph == NULL) {
67  return NULL;
68  }
69 
70  for (const GList *synapse_iter = graph->synapses;
71  synapse_iter != NULL; synapse_iter = synapse_iter->next) {
72 
73  const pcmk__graph_synapse_t *synapse = synapse_iter->data;
74 
75  for (const GList *action_iter = synapse->actions;
76  action_iter != NULL; action_iter = action_iter->next) {
77 
78  const pcmk__graph_action_t *action = action_iter->data;
79  if (action->id == id) {
80  return action;
81  }
82  }
83  }
84  return NULL;
85 }
86 
87 static const char *
88 synapse_state_str(pcmk__graph_synapse_t *synapse)
89 {
90  if (pcmk_is_set(synapse->flags, pcmk__synapse_failed)) {
91  return "Failed";
92 
93  } else if (pcmk_is_set(synapse->flags, pcmk__synapse_confirmed)) {
94  return "Completed";
95 
96  } else if (pcmk_is_set(synapse->flags, pcmk__synapse_executed)) {
97  return "In-flight";
98 
99  } else if (pcmk_is_set(synapse->flags, pcmk__synapse_ready)) {
100  return "Ready";
101  }
102  return "Pending";
103 }
104 
118 static GString *
119 synapse_pending_inputs(const pcmk__graph_t *graph,
120  const pcmk__graph_synapse_t *synapse)
121 {
122  GString *pending = NULL;
123 
124  for (const GList *lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
125  const pcmk__graph_action_t *input = (pcmk__graph_action_t *) lpc->data;
126 
128  pcmk__add_word(&pending, 1024, pcmk__xe_id(input->xml));
129 
130  } else if (pcmk_is_set(input->flags, pcmk__graph_action_confirmed)) {
131  // Confirmed successful inputs are not pending
132 
133  } else if (find_graph_action_by_id(graph, input->id) != NULL) {
134  // In-flight or pending
135  pcmk__add_word(&pending, 1024, pcmk__xe_id(input->xml));
136  }
137  }
138  return pending;
139 }
140 
141 // Log synapse inputs that aren't in graph
142 static void
143 log_unresolved_inputs(unsigned int log_level, pcmk__graph_t *graph,
144  pcmk__graph_synapse_t *synapse)
145 {
146  for (GList *lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
148  const char *key = crm_element_value(input->xml, PCMK__XA_OPERATION_KEY);
149  const char *host = crm_element_value(input->xml, PCMK__META_ON_NODE);
150 
151  if (find_graph_action_by_id(graph, input->id) == NULL) {
152  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 }
159 
160 static void
161 log_synapse_action(unsigned int log_level, pcmk__graph_synapse_t *synapse,
162  pcmk__graph_action_t *action, const char *pending_inputs)
163 {
164  const char *key = crm_element_value(action->xml, PCMK__XA_OPERATION_KEY);
165  const char *host = crm_element_value(action->xml, PCMK__META_ON_NODE);
166  char *desc = crm_strdup_printf("%s %s op %s",
167  synapse_state_str(synapse),
168  actiontype2text(action->type), key);
169 
170  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  free(desc);
175 }
176 
177 static void
178 log_synapse(unsigned int log_level, pcmk__graph_t *graph,
179  pcmk__graph_synapse_t *synapse)
180 {
181  GString *g_pending = NULL;
182  const char *pending = "none";
183 
184  if (!pcmk_is_set(synapse->flags, pcmk__synapse_executed)) {
185  g_pending = synapse_pending_inputs(graph, synapse);
186 
187  if (g_pending != NULL) {
188  pending = (const char *) g_pending->str;
189  }
190  }
191 
192  for (GList *lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
193  log_synapse_action(log_level, synapse,
194  (pcmk__graph_action_t *) lpc->data, pending);
195  }
196 
197  if (g_pending != NULL) {
198  g_string_free(g_pending, TRUE);
199  }
200 
201  if (!pcmk_is_set(synapse->flags, pcmk__synapse_executed)) {
202  log_unresolved_inputs(log_level, graph, synapse);
203  }
204 }
205 
206 void
208 {
209  log_synapse(log_level, NULL, action->synapse);
210 }
211 
212 void
213 pcmk__log_graph(unsigned int log_level, pcmk__graph_t *graph)
214 {
215  if ((graph == NULL) || (graph->num_actions == 0)) {
216  if (log_level == LOG_TRACE) {
217  crm_debug("Empty transition graph");
218  }
219  return;
220  }
221 
222  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  for (GList *lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
229  log_synapse(log_level, graph, (pcmk__graph_synapse_t *) lpc->data);
230  }
231 }
#define LOG_TRACE
Definition: logging.h:38
#define PCMK__XA_OPERATION_KEY
pcmk__cpg_host_t host
Definition: cpg.c:52
A dumping ground.
pcmk__graph_action_type
const char * pcmk__graph_status2text(enum pcmk__graph_status state)
enum crm_ais_msg_types type
Definition: cpg.c:51
#define PCMK__META_ON_NODE
const char * action
Definition: pcmk_fence.c:30
#define PCMK_OPT_BATCH_LIMIT
Definition: options.h:27
#define crm_debug(fmt, args...)
Definition: logging.h:402
pcmk__graph_status
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:458
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:181
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:94
Wrappers for and extensions to libxml2.
void pcmk__log_graph_action(int log_level, pcmk__graph_action_t *action)
xmlNode * input
void pcmk__log_graph(unsigned int log_level, pcmk__graph_t *graph)