pacemaker  2.1.6-802a72226b
Scalable High-Availability cluster resource manager
pcmk_graph_logging.c
Go to the documentation of this file.
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 
25 const char *
27 {
28  switch (state) {
29  case pcmk__graph_active:
30  return "active";
32  return "pending";
34  return "complete";
36  return "terminated";
37  }
38  return "unknown";
39 }
40 
41 static const char *
42 actiontype2text(enum pcmk__graph_action_type type)
43 {
44  switch (type) {
46  return "pseudo";
48  return "resource";
50  return "cluster";
51  }
52  return "invalid";
53 }
54 
64 static const pcmk__graph_action_t *
65 find_graph_action_by_id(const pcmk__graph_t *graph, int id)
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)
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 
122 static GString *
123 synapse_pending_inputs(const pcmk__graph_t *graph,
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 
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,
148  pcmk__graph_synapse_t *synapse)
149 {
150  for (GList *lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
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,
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,
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
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)
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 }
#define LOG_TRACE
Definition: logging.h:37
pcmk__cpg_host_t host
Definition: cpg.c:49
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:48
const char * action
Definition: pcmk_fence.c:30
#define XML_LRM_ATTR_TASK_KEY
Definition: msg_xml.h:316
#define crm_debug(fmt, args...)
Definition: logging.h:382
pcmk__graph_status
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:496
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:172
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:121
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)
#define XML_LRM_ATTR_TARGET
Definition: msg_xml.h:317
#define ID(x)
Definition: msg_xml.h:480