pacemaker  2.1.5-b7adf64e51
Scalable High-Availability cluster resource manager
xml_internal.h
Go to the documentation of this file.
1 /*
2  * Copyright 2017-2021 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 #ifndef PCMK__XML_INTERNAL__H
11 # define PCMK__XML_INTERNAL__H
12 
13 /*
14  * Internal-only wrappers for and extensions to libxml2 (libxslt)
15  */
16 
17 # include <stdlib.h>
18 # include <stdio.h>
19 # include <string.h>
20 
21 # include <crm/crm.h> /* transitively imports qblog.h */
22 
23 
67 #define PCMK__XML_LOG_BASE(priority, dechunk, postemit, prefix, fmt, ap) \
68 do { \
69  if (!(dechunk) && (prefix) == NULL) { /* quick pass */ \
70  qb_log_from_external_source_va(__func__, __FILE__, (fmt), \
71  (priority), __LINE__, 0, (ap)); \
72  (void) (postemit); \
73  } else { \
74  int CXLB_len = 0; \
75  char *CXLB_buf = NULL; \
76  static int CXLB_buffer_len = 0; \
77  static char *CXLB_buffer = NULL; \
78  static uint8_t CXLB_priority = 0; \
79  \
80  CXLB_len = vasprintf(&CXLB_buf, (fmt), (ap)); \
81  \
82  if (CXLB_len <= 0 || CXLB_buf[CXLB_len - 1] == '\n' || !(dechunk)) { \
83  if (CXLB_len < 0) { \
84  CXLB_buf = (char *) "LOG CORRUPTION HAZARD"; /*we don't modify*/\
85  CXLB_priority = QB_MIN(CXLB_priority, LOG_ERR); \
86  } else if (CXLB_len > 0 /* && (dechunk) */ \
87  && CXLB_buf[CXLB_len - 1] == '\n') { \
88  CXLB_buf[CXLB_len - 1] = '\0'; \
89  } \
90  if (CXLB_buffer) { \
91  qb_log_from_external_source(__func__, __FILE__, "%s%s%s", \
92  CXLB_priority, __LINE__, 0, \
93  (prefix) != NULL ? (prefix) : "", \
94  CXLB_buffer, CXLB_buf); \
95  free(CXLB_buffer); \
96  } else { \
97  qb_log_from_external_source(__func__, __FILE__, "%s%s", \
98  (priority), __LINE__, 0, \
99  (prefix) != NULL ? (prefix) : "", \
100  CXLB_buf); \
101  } \
102  if (CXLB_len < 0) { \
103  CXLB_buf = NULL; /* restore temporary override */ \
104  } \
105  CXLB_buffer = NULL; \
106  CXLB_buffer_len = 0; \
107  (void) (postemit); \
108  \
109  } else if (CXLB_buffer == NULL) { \
110  CXLB_buffer_len = CXLB_len; \
111  CXLB_buffer = CXLB_buf; \
112  CXLB_buf = NULL; \
113  CXLB_priority = (priority); /* remember as a running severest */ \
114  \
115  } else { \
116  CXLB_buffer = realloc(CXLB_buffer, 1 + CXLB_buffer_len + CXLB_len); \
117  memcpy(CXLB_buffer + CXLB_buffer_len, CXLB_buf, CXLB_len); \
118  CXLB_buffer_len += CXLB_len; \
119  CXLB_buffer[CXLB_buffer_len] = '\0'; \
120  CXLB_priority = QB_MIN(CXLB_priority, (priority)); /* severest? */ \
121  } \
122  free(CXLB_buf); \
123  } \
124 } while (0)
125 
126 /* XML search strings for guest, remote and pacemaker_remote nodes */
127 
128 /* search string to find CIB resources entries for cluster nodes */
129 #define PCMK__XP_MEMBER_NODE_CONFIG \
130  "//" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_NODES \
131  "/" XML_CIB_TAG_NODE "[not(@type) or @type='member']"
132 
133 /* search string to find CIB resources entries for guest nodes */
134 #define PCMK__XP_GUEST_NODE_CONFIG \
135  "//" XML_TAG_CIB "//" XML_CIB_TAG_CONFIGURATION "//" XML_CIB_TAG_RESOURCE \
136  "//" XML_TAG_META_SETS "//" XML_CIB_TAG_NVPAIR \
137  "[@name='" XML_RSC_ATTR_REMOTE_NODE "']"
138 
139 /* search string to find CIB resources entries for remote nodes */
140 #define PCMK__XP_REMOTE_NODE_CONFIG \
141  "//" XML_TAG_CIB "//" XML_CIB_TAG_CONFIGURATION "//" XML_CIB_TAG_RESOURCE \
142  "[@type='remote'][@provider='pacemaker']"
143 
144 /* search string to find CIB node status entries for pacemaker_remote nodes */
145 #define PCMK__XP_REMOTE_NODE_STATUS \
146  "//" XML_TAG_CIB "//" XML_CIB_TAG_STATUS "//" XML_CIB_TAG_STATE \
147  "[@" XML_NODE_IS_REMOTE "='true']"
148 
154 };
155 
156 void pcmk__strip_xml_text(xmlNode *xml);
157 const char *pcmk__xe_add_last_written(xmlNode *xe);
158 
159 xmlNode *pcmk__xe_match(const xmlNode *parent, const char *node_name,
160  const char *attr_n, const char *attr_v);
161 
162 void pcmk__xe_remove_matching_attrs(xmlNode *element,
163  bool (*match)(xmlAttrPtr, void *),
164  void *user_data);
165 
166 GString *pcmk__element_xpath(const xmlNode *xml);
167 
176 char *
178 
189  const char *filespec);
190 
199 static inline xmlNode *
200 pcmk__xml_first_child(const xmlNode *parent)
201 {
202  xmlNode *child = (parent? parent->children : NULL);
203 
204  while (child && (child->type == XML_TEXT_NODE)) {
205  child = child->next;
206  }
207  return child;
208 }
209 
218 static inline xmlNode *
219 pcmk__xml_next(const xmlNode *child)
220 {
221  xmlNode *next = (child? child->next : NULL);
222 
223  while (next && (next->type == XML_TEXT_NODE)) {
224  next = next->next;
225  }
226  return next;
227 }
228 
237 static inline xmlNode *
238 pcmk__xe_first_child(const xmlNode *parent)
239 {
240  xmlNode *child = (parent? parent->children : NULL);
241 
242  while (child && (child->type != XML_ELEMENT_NODE)) {
243  child = child->next;
244  }
245  return child;
246 }
247 
256 static inline xmlNode *
257 pcmk__xe_next(const xmlNode *child)
258 {
259  xmlNode *next = child? child->next : NULL;
260 
261  while (next && (next->type != XML_ELEMENT_NODE)) {
262  next = next->next;
263  }
264  return next;
265 }
266 
275 void
276 pcmk__xe_set_propv(xmlNodePtr node, va_list pairs);
277 
288 void
289 pcmk__xe_set_props(xmlNodePtr node, ...)
290 G_GNUC_NULL_TERMINATED;
291 
300 static inline xmlAttr *
301 pcmk__xe_first_attr(const xmlNode *xe)
302 {
303  return (xe == NULL)? NULL : xe->properties;
304 }
305 
315 char *
316 pcmk__xpath_node_id(const char *xpath, const char *node);
317 
318 /* internal XML-related utilities */
319 
321  pcmk__xf_none = 0x0000,
322  pcmk__xf_dirty = 0x0001,
326 
329  pcmk__xf_skip = 0x0040,
330  pcmk__xf_moved = 0x0080,
331 
336 
339  pcmk__xf_lazy = 0x4000,
340 };
341 
342 void pcmk__set_xml_doc_flag(xmlNode *xml, enum xml_private_flags flag);
343 
364 int
365 pcmk__xe_foreach_child(xmlNode *xml, const char *child_element_name,
366  int (*handler)(xmlNode *xml, void *userdata),
367  void *userdata);
368 
369 #endif // PCMK__XML_INTERNAL__H
char * pcmk__xml_artefact_root(enum pcmk__xml_artefact_ns ns)
Definition: xml.c:3035
A dumping ground.
xmlNode * pcmk__xe_match(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml.c:520
const char * pcmk__xe_add_last_written(xmlNode *xe)
Definition: xml.c:1176
void pcmk__xe_set_propv(xmlNodePtr node, va_list pairs)
Definition: xml.c:3085
void pcmk__set_xml_doc_flag(xmlNode *xml, enum xml_private_flags flag)
Definition: xml.c:108
char * pcmk__xpath_node_id(const char *xpath, const char *node)
Definition: xpath.c:315
void pcmk__strip_xml_text(xmlNode *xml)
Definition: xml.c:1078
void pcmk__xe_remove_matching_attrs(xmlNode *element, bool(*match)(xmlAttrPtr, void *), void *user_data)
Definition: xml.c:682
void pcmk__xe_set_props(xmlNodePtr node,...) G_GNUC_NULL_TERMINATED
Definition: xml.c:3103
xml_private_flags
Definition: xml_internal.h:320
pcmk__xml_artefact_ns
Definition: xml_internal.h:149
int pcmk__xe_foreach_child(xmlNode *xml, const char *child_element_name, int(*handler)(xmlNode *xml, void *userdata), void *userdata)
Definition: xml.c:3112
GString * pcmk__element_xpath(const xmlNode *xml)
Definition: xpath.c:281
const char * parent
Definition: cib.c:25
char * pcmk__xml_artefact_path(enum pcmk__xml_artefact_ns ns, const char *filespec)
Definition: xml.c:3063