diff --git a/lib/common/xml.c b/lib/common/xml.c index b6df79f..33a9abf 100644 --- a/lib/common/xml.c +++ b/lib/common/xml.c @@ -2275,6 +2275,7 @@ calculate_xml_digest_v1(xmlNode * input, gboolean sort, gboolean ignored) return digest; } +#if 0 static char * calculate_xml_digest_v2(xmlNode * source, gboolean do_filter) { @@ -2324,6 +2325,116 @@ calculate_xml_digest_v2(xmlNode * source, gboolean do_filter) crm_trace("End digest"); return digest; } +#endif + +static void +filter_xml(xmlNode *data, filter_t *filter, int filter_len, gboolean recursive) +{ + int lpc = 0; + xmlNode *child = NULL; + + for(lpc = 0; lpc < filter_len; lpc++) { + xml_remove_prop(data, filter[lpc].string); + } + + if(recursive == FALSE || filter_len == 0) { + return; + } + + for(child = __xml_first_child(data); child != NULL; child = __xml_next(child)) { + filter_xml(child, filter, filter_len, recursive); + } +} + +static char * +calculate_xml_digest_v2(xmlNode *source, gboolean do_filter) +{ + char *digest = NULL; + + int buffer_len = 0; + int filter_size = DIMOF(filter); + + xmlDoc *doc = NULL; + xmlNode *copy = NULL; + xmlNode *input = source; + xmlBuffer *xml_buffer = NULL; + static struct qb_log_callsite *digest_cs = NULL; + + crm_trace("Begin digest"); + if(do_filter && BEST_EFFORT_STATUS) { + /* Exclude the status calculation from the digest + * + * This doesn't mean it wont be sync'd, we just wont be paranoid + * about it being an _exact_ copy + * + * We don't need it to be exact, since we throw it away and regenerate + * from our peers whenever a new DC is elected anyway + * + * Importantly, this reduces the amount of XML to copy+export as + * well as the amount of data for MD5 needs to operate on + */ + xmlNode *child = NULL; + xmlAttrPtr pIter = NULL; + copy = create_xml_node(NULL, XML_TAG_CIB); + for(pIter = crm_first_attr(input); pIter != NULL; pIter = pIter->next) { + const char *p_name = (const char *)pIter->name; + const char *p_value = crm_attr_value(pIter); + + xmlSetProp(copy, (const xmlChar*)p_name, (const xmlChar*)p_value); + } + + xml_remove_prop(copy, XML_ATTR_ORIGIN); + xml_remove_prop(copy, XML_CIB_ATTR_WRITTEN); + + /* We just did all the filtering */ + + for(child = __xml_first_child(input); child != NULL; child = __xml_next(child)) { + if(safe_str_neq(crm_element_name(child), XML_CIB_TAG_STATUS)) { + add_node_copy(copy, child); + } + } + + } else if(do_filter) { + copy = copy_xml(input); + filter_xml(copy, filter, filter_size, TRUE); + input = copy; + } + + crm_trace("Dumping"); + doc = getDocPtr(input); + xml_buffer = xmlBufferCreate(); + + CRM_ASSERT(xml_buffer != NULL); + CRM_CHECK(doc != NULL, return NULL); /* doc will only be NULL if an_xml_node is */ + + buffer_len = xmlNodeDump(xml_buffer, doc, input, 0, FALSE); + CRM_CHECK(xml_buffer->content != NULL && buffer_len > 0, goto done); + + digest = crm_md5sum((char *)xml_buffer->content); + + if(digest_cs == NULL) { + digest_cs = qb_log_callsite_get( + __func__, __FILE__, "cib-digest", LOG_TRACE, __LINE__, + crm_trace_nonlog); + } + if (digest_cs && digest_cs->targets) { + char *trace_file = crm_concat("/tmp/cib-digest", digest, '-'); + crm_trace("Saving %s.%s.%s to %s", + crm_element_value(input, XML_ATTR_GENERATION_ADMIN), + crm_element_value(input, XML_ATTR_GENERATION), + crm_element_value(input, XML_ATTR_NUMUPDATES), + trace_file); + save_xml_to_file(source, "digest input", trace_file); + free(trace_file); + } + + done: + xmlBufferFree(xml_buffer); + free_xml(copy); + + crm_trace("End digest"); + return digest; +} char * calculate_on_disk_digest(xmlNode * input)