Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XML refactors/deprecations: crm_foreach_xpath_result() to pcmk__xml_tracking_changes() #3851

Merged
merged 20 commits into from
Mar 24, 2025
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
fb1082e
Refactor: libcrmcommon: New PCMK__XE_FILE string constant
nrwahl2 Mar 12, 2025
7f1c868
Refactor: libcrmcommon: New pcmk__xpath_foreach_result()
nrwahl2 Mar 11, 2025
0884a60
API: libcrmcommon: Deprecate crm_foreach_xpath_result()
nrwahl2 Mar 11, 2025
06329de
Refactor: fencer: Use PCMK__XA_ST_DEVICE_ACTION where appropriate
nrwahl2 Mar 13, 2025
a819753
Refactor: various: Match elements directly with get_xpath_object()
nrwahl2 Mar 13, 2025
328cc27
Refactor: libcrmcommon: New pcmk__xpath_find_one()
nrwahl2 Mar 11, 2025
941eb56
API: libcrmcommon: Deprecate get_xpath_object()
nrwahl2 Mar 11, 2025
dcf291e
Refactor: libcrmcommon: Drop unused includes from xml.h
nrwahl2 Mar 11, 2025
b80bfa7
Refactor: libcrmcommon: Drop pcmkXmlStr internally
nrwahl2 Mar 11, 2025
fc18295
API: libcrmcommon: Deprecate pcmkXmlStr
nrwahl2 Mar 11, 2025
413e601
Refactor: libcrmcommon: Take doc as argument in pcmk__set_xml_doc_flag()
nrwahl2 Mar 12, 2025
cdf8a3d
Refactor: libcrmcommon: New pcmk__xml_doc_all_flags_set()
nrwahl2 May 5, 2024
7718289
Refactor: libcrmcommon: Drop xml_tracking_changes() internally
nrwahl2 Mar 11, 2025
08bc463
API: libcrmcommon: Deprecate xml_tracking_changes()
nrwahl2 Mar 11, 2025
2b1f3c7
Refactor: libcrmcommon: Drop xml_document_dirty() internally
nrwahl2 Mar 11, 2025
65d4443
API: libcrmcommon: Deprecate xml_document_dirty()
nrwahl2 Mar 11, 2025
5da49c4
Refactor: libcrmcommon: Drop pcmk__tracking_xml_changes()
nrwahl2 Mar 11, 2025
162691c
Doc: libcrmservice: Classify two Coverity defects as false positives
nrwahl2 Mar 12, 2025
3aeb505
Refactor: libcrmcommon: Rename xml_doc_private_t:user to acl_user
nrwahl2 Mar 12, 2025
3f0f056
Refactor: libcrmcommon: pcmk__xe_remove_matching_attrs() new force arg
nrwahl2 Mar 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions daemons/execd/remoted_schemas.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023-2024 the Pacemaker project contributors
* Copyright 2023-2025 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
Expand Down Expand Up @@ -185,8 +185,8 @@ get_schema_files(void)
* than what the cluster supports, we'll get back an empty <schemas> node,
* so all this will continue to work. It just won't do anything.
*/
crm_foreach_xpath_result(reply, "//" PCMK_XA_FILE,
write_extra_schema_file, NULL);
pcmk__xpath_foreach_result(reply->doc, "//" PCMK__XE_FILE,
write_extra_schema_file, NULL);
}

pcmk__xml_free(reply);
Expand Down
20 changes: 10 additions & 10 deletions daemons/fenced/fenced_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ create_async_command(xmlNode *msg)
return NULL;
}

op = get_xpath_object("//@" PCMK__XE_ST_DEVICE_ACTION, msg, LOG_ERR);
op = get_xpath_object("//*[@" PCMK__XA_ST_DEVICE_ACTION "]", msg, LOG_ERR);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look carefully through this commit please, and anything else that modifies actual XPath expressions. We're not going to get a compile time error for bad XPath syntax, or for good syntax that no longer matches what we want to.

if (op == NULL) {
return NULL;
}
Expand Down Expand Up @@ -1895,7 +1895,7 @@ static void
execute_agent_action(xmlNode *msg, pcmk__action_result_t *result)
{
xmlNode *dev = get_xpath_object("//" PCMK__XE_ST_DEVICE_ID, msg, LOG_ERR);
xmlNode *op = get_xpath_object("//@" PCMK__XE_ST_DEVICE_ACTION, msg,
xmlNode *op = get_xpath_object("//*[@" PCMK__XA_ST_DEVICE_ACTION "]", msg,
LOG_ERR);
const char *id = crm_element_value(dev, PCMK__XA_ST_DEVICE_ID);
const char *action = crm_element_value(op, PCMK__XA_ST_DEVICE_ACTION);
Expand Down Expand Up @@ -2851,7 +2851,7 @@ fence_locally(xmlNode *msg, pcmk__action_result_t *result)

CRM_CHECK((msg != NULL) && (result != NULL), return);

dev = get_xpath_object("//@" PCMK__XA_ST_TARGET, msg, LOG_ERR);
dev = get_xpath_object("//*[@" PCMK__XA_ST_TARGET "]", msg, LOG_ERR);

cmd = create_async_command(msg);
if (cmd == NULL) {
Expand Down Expand Up @@ -3041,8 +3041,8 @@ check_alternate_host(const char *target)
static void
remove_relay_op(xmlNode * request)
{
xmlNode *dev = get_xpath_object("//@" PCMK__XE_ST_DEVICE_ACTION, request,
LOG_TRACE);
xmlNode *dev = get_xpath_object("//*[@" PCMK__XA_ST_DEVICE_ACTION "]",
request, LOG_TRACE);
const char *relay_op_id = NULL;
const char *op_id = NULL;
const char *client_name = NULL;
Expand Down Expand Up @@ -3182,7 +3182,7 @@ handle_query_request(pcmk__request_t *request)

pcmk__set_result(&request->result, CRM_EX_OK, PCMK_EXEC_DONE, NULL);

dev = get_xpath_object("//@" PCMK__XE_ST_DEVICE_ACTION, request->xml,
dev = get_xpath_object("//*[@" PCMK__XA_ST_DEVICE_ACTION "]", request->xml,
LOG_NEVER);
if (dev != NULL) {
const char *device = crm_element_value(dev, PCMK__XA_ST_DEVICE_ID);
Expand Down Expand Up @@ -3246,8 +3246,8 @@ handle_notify_request(pcmk__request_t *request)
static xmlNode *
handle_relay_request(pcmk__request_t *request)
{
xmlNode *dev = get_xpath_object("//@" PCMK__XA_ST_TARGET, request->xml,
LOG_TRACE);
xmlNode *dev = get_xpath_object("//*[@" PCMK__XA_ST_TARGET "]",
request->xml, LOG_TRACE);

crm_notice("Received forwarded fencing request from "
"%s %s to fence (%s) peer %s",
Expand Down Expand Up @@ -3290,8 +3290,8 @@ handle_fence_request(pcmk__request_t *request)

} else {
const char *alternate_host = NULL;
xmlNode *dev = get_xpath_object("//@" PCMK__XA_ST_TARGET, request->xml,
LOG_TRACE);
xmlNode *dev = get_xpath_object("//*[@" PCMK__XA_ST_TARGET "]",
request->xml, LOG_TRACE);
const char *target = crm_element_value(dev, PCMK__XA_ST_TARGET);
const char *action = crm_element_value(dev, PCMK__XA_ST_DEVICE_ACTION);
const char *device = crm_element_value(dev, PCMK__XA_ST_DEVICE_ID);
Expand Down
5 changes: 3 additions & 2 deletions daemons/fenced/fenced_history.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2024 the Pacemaker project contributors
* Copyright 2009-2025 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
Expand Down Expand Up @@ -477,7 +477,8 @@ stonith_fence_history(xmlNode *msg, xmlNode **output,
const char *remote_peer, int options)
{
const char *target = NULL;
xmlNode *dev = get_xpath_object("//@" PCMK__XA_ST_TARGET, msg, LOG_NEVER);
xmlNode *dev = get_xpath_object("//*[@" PCMK__XA_ST_TARGET "]", msg,
LOG_NEVER);
xmlNode *out_history = NULL;

if (dev) {
Expand Down
16 changes: 10 additions & 6 deletions daemons/fenced/fenced_remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ finalize_op_duplicates(remote_fencing_op_t *op, xmlNode *data)
static char *
delegate_from_xml(xmlNode *xml)
{
xmlNode *match = get_xpath_object("//@" PCMK__XA_ST_DELEGATE, xml,
xmlNode *match = get_xpath_object("//*[@" PCMK__XA_ST_DELEGATE "]", xml,
LOG_NEVER);

if (match == NULL) {
Expand Down Expand Up @@ -1110,7 +1110,8 @@ int
fenced_handle_manual_confirmation(const pcmk__client_t *client, xmlNode *msg)
{
remote_fencing_op_t *op = NULL;
xmlNode *dev = get_xpath_object("//@" PCMK__XA_ST_TARGET, msg, LOG_ERR);
xmlNode *dev = get_xpath_object("//*[@" PCMK__XA_ST_TARGET "]", msg,
LOG_ERR);

CRM_CHECK(dev != NULL, return EPROTO);

Expand Down Expand Up @@ -1149,7 +1150,7 @@ void *
create_remote_stonith_op(const char *client, xmlNode *request, gboolean peer)
{
remote_fencing_op_t *op = NULL;
xmlNode *dev = get_xpath_object("//@" PCMK__XA_ST_TARGET, request,
xmlNode *dev = get_xpath_object("//*[@" PCMK__XA_ST_TARGET "]", request,
LOG_NEVER);
int rc = pcmk_rc_ok;
const char *operation = NULL;
Expand Down Expand Up @@ -2336,14 +2337,16 @@ process_remote_stonith_query(xmlNode *msg)
remote_fencing_op_t *op = NULL;
peer_device_info_t *peer = NULL;
uint32_t replies_expected;
xmlNode *dev = get_xpath_object("//@" PCMK__XA_ST_REMOTE_OP, msg, LOG_ERR);
xmlNode *dev = get_xpath_object("//*[@" PCMK__XA_ST_REMOTE_OP "]", msg,
LOG_ERR);

CRM_CHECK(dev != NULL, return -EPROTO);

id = crm_element_value(dev, PCMK__XA_ST_REMOTE_OP);
CRM_CHECK(id != NULL, return -EPROTO);

dev = get_xpath_object("//@" PCMK__XA_ST_AVAILABLE_DEVICES, msg, LOG_ERR);
dev = get_xpath_object("//*[@" PCMK__XA_ST_AVAILABLE_DEVICES "]", msg,
LOG_ERR);
CRM_CHECK(dev != NULL, return -EPROTO);
crm_element_value_int(dev, PCMK__XA_ST_AVAILABLE_DEVICES, &ndevices);

Expand Down Expand Up @@ -2434,7 +2437,8 @@ fenced_process_fencing_reply(xmlNode *msg)
const char *id = NULL;
const char *device = NULL;
remote_fencing_op_t *op = NULL;
xmlNode *dev = get_xpath_object("//@" PCMK__XA_ST_REMOTE_OP, msg, LOG_ERR);
xmlNode *dev = get_xpath_object("//*[@" PCMK__XA_ST_REMOTE_OP "]", msg,
LOG_ERR);
pcmk__action_result_t result = PCMK__UNKNOWN_RESULT;

CRM_CHECK(dev != NULL, return);
Expand Down
3 changes: 0 additions & 3 deletions include/crm/common/xml.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ typedef const xmlChar *pcmkXmlStr;
// NOTE: sbd (as of at least 1.5.2) uses this
xmlNode *get_xpath_object(const char *xpath, xmlNode * xml_obj, int error_level);

void crm_foreach_xpath_result(xmlNode *xml, const char *xpath,
void (*helper)(xmlNode*, void*), void *user_data);

bool xml_tracking_changes(xmlNode * xml);
bool xml_document_dirty(xmlNode *xml);
void xml_track_changes(xmlNode * xml, const char *user, xmlNode *acl_source, bool enforce_acls);
Expand Down
4 changes: 4 additions & 0 deletions include/crm/common/xml_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ void freeXpathObject(xmlXPathObjectPtr xpathObj);
//! \deprecated Do not use
void dedupXpathResults(xmlXPathObjectPtr xpathObj);

//! \deprecated Do not use
void crm_foreach_xpath_result(xmlNode *xml, const char *xpath,
void (*helper)(xmlNode*, void*), void *user_data);

#ifdef __cplusplus
}
#endif
Expand Down
3 changes: 2 additions & 1 deletion include/crm/common/xml_names_internal.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2004-2024 the Pacemaker project contributors
* Copyright 2004-2025 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
Expand Down Expand Up @@ -35,6 +35,7 @@ extern "C" {
#define PCMK__XE_DOWNED "downed"
#define PCMK__XE_EXIT_NOTIFICATION "exit-notification"
#define PCMK__XE_FAILED_UPDATE "failed_update"
#define PCMK__XE_FILE "file"
#define PCMK__XE_GENERATION_TUPLE "generation_tuple"
#define PCMK__XE_INPUTS "inputs"
#define PCMK__XE_LRM "lrm"
Expand Down
2 changes: 2 additions & 0 deletions include/crm/common/xpath_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ char *pcmk__xpath_node_id(const char *xpath, const char *node);
xmlXPathObject *pcmk__xpath_search(xmlDoc *doc, const char *path);
xmlNode *pcmk__xpath_result(xmlXPathObject *xpath_obj, int index);
xmlNode *pcmk__xpath_match_element(xmlNode *match);
void pcmk__xpath_foreach_result(xmlDoc *doc, const char *path,
void (*fn)(xmlNode *, void *), void *user_data);

void pcmk__warn_multiple_name_matches(pcmk__output_t *out, xmlNode *search,
const char *name);
Expand Down
18 changes: 9 additions & 9 deletions lib/cluster/membership.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2004-2024 the Pacemaker project contributors
* Copyright 2004-2025 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
Expand Down Expand Up @@ -337,8 +337,8 @@ refresh_remote_nodes(xmlNode *cib)
/* Look for guest nodes and remote nodes in the status section */
data.field = PCMK_XA_ID;
data.has_state = TRUE;
crm_foreach_xpath_result(cib, PCMK__XP_REMOTE_NODE_STATUS,
remote_cache_refresh_helper, &data);
pcmk__xpath_foreach_result(cib->doc, PCMK__XP_REMOTE_NODE_STATUS,
remote_cache_refresh_helper, &data);

/* Look for guest nodes and remote nodes in the configuration section,
* because they may have just been added and not have a status entry yet.
Expand All @@ -348,12 +348,12 @@ refresh_remote_nodes(xmlNode *cib)
*/
data.field = PCMK_XA_VALUE;
data.has_state = FALSE;
crm_foreach_xpath_result(cib, PCMK__XP_GUEST_NODE_CONFIG,
remote_cache_refresh_helper, &data);
pcmk__xpath_foreach_result(cib->doc, PCMK__XP_GUEST_NODE_CONFIG,
remote_cache_refresh_helper, &data);
data.field = PCMK_XA_ID;
data.has_state = FALSE;
crm_foreach_xpath_result(cib, PCMK__XP_REMOTE_NODE_CONFIG,
remote_cache_refresh_helper, &data);
pcmk__xpath_foreach_result(cib->doc, PCMK__XP_REMOTE_NODE_CONFIG,
remote_cache_refresh_helper, &data);

/* Remove all old cache entries that weren't seen in the CIB */
g_hash_table_foreach_remove(pcmk__remote_peer_cache, is_dirty, NULL);
Expand Down Expand Up @@ -1490,8 +1490,8 @@ refresh_cluster_node_cib_cache(xmlNode *cib)

g_hash_table_foreach(cluster_node_cib_cache, mark_dirty, NULL);

crm_foreach_xpath_result(cib, PCMK__XP_MEMBER_NODE_CONFIG,
cluster_node_cib_cache_refresh_helper, NULL);
pcmk__xpath_foreach_result(cib->doc, PCMK__XP_MEMBER_NODE_CONFIG,
cluster_node_cib_cache_refresh_helper, NULL);

// Remove all old cache entries that weren't seen in the CIB
g_hash_table_foreach_remove(cluster_node_cib_cache, is_dirty, NULL);
Expand Down
4 changes: 2 additions & 2 deletions lib/common/schemas.c
Original file line number Diff line number Diff line change
Expand Up @@ -1427,7 +1427,7 @@ external_refs_in_schema(GList **list, const char *contents)
const char *search = "//*[local-name()='externalRef'] | //*[local-name()='include']";
xmlNode *xml = pcmk__xml_parse(contents);

crm_foreach_xpath_result(xml, search, append_href, list);
pcmk__xpath_foreach_result(xml->doc, search, append_href, list);
pcmk__xml_free(xml);
}

Expand Down Expand Up @@ -1482,7 +1482,7 @@ add_schema_file_to_xml(xmlNode *parent, const char *file, GList **already_includ
/* Create a new <file path="..."> node with the contents of the file
* as a CDATA block underneath it.
*/
file_node = pcmk__xe_create(parent, PCMK_XA_FILE);
file_node = pcmk__xe_create(parent, PCMK__XE_FILE);
crm_xml_add(file_node, PCMK_XA_PATH, path);
*already_included = g_list_prepend(*already_included, path);

Expand Down
79 changes: 52 additions & 27 deletions lib/common/xpath.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,45 +148,40 @@ pcmk__xpath_search(xmlDoc *doc, const char *path)
}

/*!
* \brief Run a supplied function for each result of an xpath search
* \internal
* \brief Run a supplied function for each result of an XPath search
*
* \param[in,out] xml XML to search
* \param[in] xpath XPath search string
* \param[in] helper Function to call for each result
* \param[in,out] user_data Data to pass to supplied function
* \param[in,out] doc XML document to search
* \param[in] path XPath expression to evaluate in the context of
* \p doc
* \param[in] fn Function to call for each result XML element
* \param[in,out] user_data Data to pass to \p fn
*
* \note The helper function will be passed the XML node of the result,
* and the supplied user_data. This function does not otherwise
* use user_data.
* \note This function processes the result node set in forward order. If \p fn
* may free any part of any result node, then it is safer to process the
* result node set in reverse order. (The node set is in document order.)
* See comments in libxml's <tt>examples/xpath2.c</tt> file.
*/
void
crm_foreach_xpath_result(xmlNode *xml, const char *xpath,
void (*helper)(xmlNode*, void*), void *user_data)
pcmk__xpath_foreach_result(xmlDoc *doc, const char *path,
void (*fn)(xmlNode *, void *), void *user_data)
{
xmlXPathObject *xpathObj = NULL;
int nresults = 0;

CRM_CHECK(xml != NULL, return);
xmlXPathObject *xpath_obj = NULL;
int num_results = 0;

xpathObj = pcmk__xpath_search(xml->doc, xpath);
nresults = pcmk__xpath_num_results(xpathObj);
CRM_CHECK((doc != NULL) && !pcmk__str_empty(path) && (fn != NULL), return);

for (int i = 0; i < nresults; i++) {
xmlNode *result = pcmk__xpath_result(xpathObj, i);
xpath_obj = pcmk__xpath_search(doc, path);
num_results = pcmk__xpath_num_results(xpath_obj);

CRM_LOG_ASSERT(result != NULL);
for (int i = 0; i < num_results; i++) {
xmlNode *result = pcmk__xpath_result(xpath_obj, i);

if (result != NULL) {
result = pcmk__xpath_match_element(result);

CRM_LOG_ASSERT(result != NULL);

if (result != NULL) {
(*helper)(result, user_data);
}
(*fn)(result, user_data);
}
}
xmlXPathFreeObject(xpathObj);
xmlXPathFreeObject(xpath_obj);
}

xmlNode *
Expand Down Expand Up @@ -484,5 +479,35 @@ dedupXpathResults(xmlXPathObjectPtr xpathObj)
}
}

void
crm_foreach_xpath_result(xmlNode *xml, const char *xpath,
void (*helper)(xmlNode*, void*), void *user_data)
{
xmlXPathObject *xpathObj = NULL;
int nresults = 0;

CRM_CHECK(xml != NULL, return);

xpathObj = pcmk__xpath_search(xml->doc, xpath);
nresults = pcmk__xpath_num_results(xpathObj);

for (int i = 0; i < nresults; i++) {
xmlNode *result = pcmk__xpath_result(xpathObj, i);

CRM_LOG_ASSERT(result != NULL);

if (result != NULL) {
result = pcmk__xpath_match_element(result);

CRM_LOG_ASSERT(result != NULL);

if (result != NULL) {
(*helper)(result, user_data);
}
}
}
xmlXPathFreeObject(xpathObj);
}

// LCOV_EXCL_STOP
// End deprecated API
5 changes: 3 additions & 2 deletions lib/fencing/st_actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -468,13 +468,14 @@ stonith__xe_set_result(xmlNode *xml, const pcmk__action_result_t *result)
xmlNode *
stonith__find_xe_with_result(xmlNode *xml)
{
xmlNode *match = get_xpath_object("//@" PCMK__XA_RC_CODE, xml, LOG_NEVER);
xmlNode *match = get_xpath_object("//*[@" PCMK__XA_RC_CODE "]", xml,
LOG_NEVER);

if (match == NULL) {
/* @COMPAT Peers <=2.1.2 in a rolling upgrade provide only a legacy
* return code, not a full result, so check for that.
*/
match = get_xpath_object("//@" PCMK__XA_ST_RC, xml, LOG_ERR);
match = get_xpath_object("//*[@" PCMK__XA_ST_RC "]", xml, LOG_ERR);
}
return match;
}
Expand Down
Loading