Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F2020000
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/crm/cib/cibprimatives.c b/crm/cib/cibprimatives.c
index 01f082c1a4..ebff5cb416 100644
--- a/crm/cib/cibprimatives.c
+++ b/crm/cib/cibprimatives.c
@@ -1,592 +1,599 @@
-/* $Id: cibprimatives.c,v 1.29 2004/05/23 19:54:04 andrew Exp $ */
+/* $Id: cibprimatives.c,v 1.30 2004/05/26 07:05:43 andrew Exp $ */
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <portability.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <crm/crm.h>
#include <clplumbing/cl_log.h>
#include <libxml/tree.h>
#include <cibprimatives.h>
#include <crm/msg_xml.h>
#include <crm/common/xmlutils.h>
#include <crm/common/crmutils.h>
#include <crm/cib.h>
#include <crm/dmalloc_wrapper.h>
/*
* In case of confusion, this is the memory management policy for
* all functions in this file.
*
* All add/modify functions use copies of supplied data.
* It is therefore appropriate that the callers free the supplied data
* at some point after the function has finished.
*
* All delete functions will handle the freeing of deleted data
* but not the function arguments.
*/
void update_node_state(xmlNodePtr existing_node, xmlNodePtr update);
//--- Resource
int
addResource(xmlNodePtr cib, xmlNodePtr anXmlNode)
{
const char *id = ID(anXmlNode);
xmlNodePtr root;
if (id == NULL || strlen(id) < 1) {
return CIBRES_MISSING_ID;
}
CRM_DEBUG("Adding " XML_CIB_TAG_RESOURCE " (%s)...", id);
root = get_object_root(XML_CIB_TAG_RESOURCES, cib);
return add_cib_object(root, anXmlNode);
}
xmlNodePtr
findResource(xmlNodePtr cib, const char *id)
{
xmlNodePtr root = NULL, ret = NULL;
FNIN();
root = get_object_root(XML_CIB_TAG_RESOURCES, cib);
ret = find_entity(root, XML_CIB_TAG_RESOURCE, id, FALSE);
FNRET(ret);
}
int
updateResource(xmlNodePtr cib, xmlNodePtr anXmlNode)
{
const char *id = ID(anXmlNode);
xmlNodePtr root;
if (id == NULL || strlen(id) < 1) {
return CIBRES_MISSING_ID;
}
CRM_DEBUG("Updating " XML_CIB_TAG_RESOURCE " (%s)...", id);
root = get_object_root(XML_CIB_TAG_RESOURCES, cib);
return update_cib_object(root, anXmlNode, FALSE);
}
int
delResource(xmlNodePtr cib, xmlNodePtr delete_spec)
{
const char *id = ID(delete_spec);
xmlNodePtr root;
if(id == NULL || strlen(id) == 0) {
return CIBRES_MISSING_ID;
}
CRM_DEBUG("Deleting " XML_CIB_TAG_RESOURCE " (%s)...", id);
root = get_object_root(XML_CIB_TAG_RESOURCES, cib);
return delete_cib_object(root, delete_spec);
}
//--- Constraint
int
addConstraint(xmlNodePtr cib, xmlNodePtr anXmlNode)
{
const char *id = ID(anXmlNode);
xmlNodePtr root;
if (id == NULL || strlen(id) < 1) {
return CIBRES_MISSING_ID;
}
CRM_DEBUG("Adding " XML_CIB_TAG_CONSTRAINT " (%s)...", id);
root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib);
return add_cib_object(root, anXmlNode);
}
xmlNodePtr
findConstraint(xmlNodePtr cib, const char *id)
{
xmlNodePtr root = NULL, ret = NULL;
FNIN();
root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib);
ret = find_entity(root, XML_CIB_TAG_CONSTRAINT, id, FALSE);
FNRET(ret);
}
int
updateConstraint(xmlNodePtr cib, xmlNodePtr anXmlNode)
{
const char *id = ID(anXmlNode);
xmlNodePtr root;
if (id == NULL || strlen(id) < 1) {
return CIBRES_MISSING_ID;
}
CRM_DEBUG("Updating " XML_CIB_TAG_CONSTRAINT " (%s)...", id);
root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib);
return update_cib_object(root, anXmlNode, FALSE);
}
int
delConstraint(xmlNodePtr cib, xmlNodePtr delete_spec)
{
const char *id = ID(delete_spec);
xmlNodePtr root;
if(id == NULL || strlen(id) == 0) {
return CIBRES_MISSING_ID;
}
CRM_DEBUG("Deleting " XML_CIB_TAG_CONSTRAINT " (%s)...", id);
root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib);
return delete_cib_object(root, delete_spec);
}
//--- HaNode
int
addHaNode(xmlNodePtr cib, xmlNodePtr anXmlNode)
{
const char *id = ID(anXmlNode);
xmlNodePtr root;
if (id == NULL || strlen(id) < 1) {
return CIBRES_MISSING_ID;
}
CRM_DEBUG("Adding " XML_CIB_TAG_NODE " (%s)...", id);
root = get_object_root(XML_CIB_TAG_NODES, cib);
return add_cib_object(root, anXmlNode);
}
xmlNodePtr
findHaNode(xmlNodePtr cib, const char *id)
{
xmlNodePtr root = NULL, ret = NULL;
FNIN();
root = get_object_root(XML_CIB_TAG_NODES, cib);
ret = find_entity(root, XML_CIB_TAG_NODE, id, FALSE);
FNRET(ret);
}
int
updateHaNode(xmlNodePtr cib, cibHaNode *anXmlNode)
{
const char *id = ID(anXmlNode);
xmlNodePtr root;
if (id == NULL || strlen(id) < 1) {
return CIBRES_MISSING_ID;
}
CRM_DEBUG("Updating " XML_CIB_TAG_NODE " (%s)...", id);
root = get_object_root(XML_CIB_TAG_NODES, cib);
return update_cib_object(root, anXmlNode, FALSE);
}
int
delHaNode(xmlNodePtr cib, xmlNodePtr delete_spec)
{
const char *id = ID(delete_spec);
xmlNodePtr root;
if(id == NULL || strlen(id) == 0) {
return CIBRES_MISSING_ID;
}
CRM_DEBUG("Deleting " XML_CIB_TAG_NODE " (%s)...", id);
root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib);
return delete_cib_object(root, delete_spec);
}
//--- Status
int
addStatus(xmlNodePtr cib, xmlNodePtr anXmlNode)
{
const char *id = ID(anXmlNode);
xmlNodePtr root;
if (id == NULL || strlen(id) < 1) {
return CIBRES_MISSING_ID;
}
CRM_DEBUG("Adding " XML_CIB_TAG_NODE " (%s)...", id);
root = get_object_root(XML_CIB_TAG_STATUS, cib);
return add_cib_object(root, anXmlNode);
}
xmlNodePtr
findStatus(xmlNodePtr cib, const char *id)
{
xmlNodePtr root = NULL, ret = NULL;
root = get_object_root(XML_CIB_TAG_STATUS, cib);
ret = find_entity(root, XML_CIB_TAG_STATE, id, FALSE);
FNRET(ret);
}
int
updateStatus(xmlNodePtr cib, xmlNodePtr anXmlNode)
{
const char *id = ID(anXmlNode);
xmlNodePtr root;
if (id == NULL || strlen(id) < 1) {
return CIBRES_MISSING_ID;
}
CRM_DEBUG("Updating " XML_CIB_TAG_NODE " (%s)...", id);
root = get_object_root(XML_CIB_TAG_STATUS, cib);
return update_cib_object(root, anXmlNode, FALSE);
}
int
delStatus(xmlNodePtr cib, xmlNodePtr delete_spec)
{
const char *id = ID(delete_spec);
xmlNodePtr root;
if(id == NULL || strlen(id) == 0) {
return CIBRES_MISSING_ID;
}
CRM_DEBUG("Deleting " XML_CIB_TAG_STATE " (%s)...", id);
root = get_object_root(XML_CIB_TAG_STATUS, cib);
return delete_cib_object(root, delete_spec);
}
int
delete_cib_object(xmlNodePtr parent, xmlNodePtr delete_spec)
{
const char *object_name = NULL;
const char *object_id = NULL;
xmlNodePtr equiv_node = NULL;
xmlNodePtr children = NULL;
int result = CIBRES_OK;
if(delete_spec == NULL) {
return CIBRES_FAILED_NOOBJECT;
} else if(parent == NULL) {
return CIBRES_FAILED_NOPARENT;
}
object_name = delete_spec->name;
object_id = xmlGetProp(delete_spec, XML_ATTR_ID);
children = delete_spec->children;
if(object_id == NULL) {
// placeholder object
equiv_node = find_xml_node(parent, object_name);
} else {
equiv_node =
find_entity(parent, object_name, object_id, FALSE);
}
if(equiv_node == NULL) {
return CIBRES_FAILED_NOTEXISTS;
} else if(children == NULL) {
// only leaves are deleted
unlink_xml_node(equiv_node);
free_xml(equiv_node);
} else {
while(children != NULL) {
int tmp_result =
delete_cib_object(equiv_node, children);
// only the first error is likely to be interesting
if(tmp_result != CIBRES_OK
&& result == CIBRES_OK) {
result = tmp_result;
}
children = children->next;
}
}
return result;
}
int
add_cib_object(xmlNodePtr parent, xmlNodePtr new_obj)
{
const char *object_name = NULL;
const char *object_id = NULL;
xmlNodePtr equiv_node = NULL;
xmlNodePtr children = NULL;
if(new_obj == NULL) {
return CIBRES_FAILED_NOOBJECT;
} else if(parent == NULL) {
return CIBRES_FAILED_NOPARENT;
}
object_name = new_obj->name;
object_id = xmlGetProp(new_obj, XML_ATTR_ID);
children = new_obj->children;
if(object_id == NULL) {
// placeholder object
equiv_node = find_xml_node(parent, object_name);
} else {
equiv_node =
find_entity(parent, object_name, object_id, FALSE);
}
if(equiv_node != NULL) {
return CIBRES_FAILED_EXISTS;
} else if(add_node_copy(parent, new_obj) == NULL) {
return CIBRES_FAILED_NODECOPY;
}
return CIBRES_OK;
}
int
update_cib_object(xmlNodePtr parent, xmlNodePtr new_obj, gboolean force)
{
const char *object_name = NULL;
const char *object_id = NULL;
xmlNodePtr equiv_node = NULL;
xmlNodePtr children = NULL;
int result = CIBRES_OK;
if(new_obj == NULL) {
return CIBRES_FAILED_NOOBJECT;
} else if(parent == NULL) {
return CIBRES_FAILED_NOPARENT;
}
object_name = new_obj->name;
object_id = xmlGetProp(new_obj, XML_ATTR_ID);
children = new_obj->children;
if(object_id == NULL) {
// placeholder object
equiv_node = find_xml_node(parent, object_name);
} else {
equiv_node =
find_entity(parent, object_name, object_id, FALSE);
}
if(equiv_node != NULL) {
if(force == FALSE) {
const char *ts_existing = NULL;
const char *ts_new = NULL;
/* default to false?
*
* that would mean every node would have to
* carry a timestamp
*/
gboolean is_update = TRUE;
ts_existing = TSTAMP(equiv_node);
ts_new = TSTAMP(new_obj);
if(ts_new != NULL && ts_existing != NULL) {
is_update = (strcmp(ts_new, ts_existing) > 0);
}
if(is_update == FALSE) {
cl_log(LOG_ERR,
"Ignoring old update to <%s id=\"%s\">"
"(%s vs. %s)",
object_name, object_id,
ts_new, ts_existing);
return CIBRES_FAILED_STALE;
}
}
if(safe_str_eq(XML_CIB_TAG_STATE, object_name)){
update_node_state(equiv_node, new_obj);
} else {
copy_in_properties(equiv_node, new_obj);
}
while(children != NULL) {
int tmp_result =
update_cib_object(equiv_node, children,force);
// only the first error is likely to be interesting
if(tmp_result != CIBRES_OK
&& result == CIBRES_OK) {
result = tmp_result;
}
children = children->next;
}
} else if(add_node_copy(parent, new_obj) == NULL) {
return CIBRES_FAILED_NODECOPY;
}
return result;
}
void
update_node_state(xmlNodePtr target, xmlNodePtr update)
{
gboolean any_updates = FALSE;
gboolean replace_lrm = FALSE;
const char *old_state = xmlGetProp(target, "state");
const char *old_unclean = xmlGetProp(target, "unclean");
const char *source = NULL;
const char *unclean = NULL;
const char *exp_state = NULL;
const char *state = NULL;
xmlAttrPtr prop_iter = NULL;
FNIN();
prop_iter = update->properties;
while(prop_iter != NULL) {
const char *local_prop_name = prop_iter->name;
const char *local_prop_value =
xmlGetProp(update, local_prop_name);
if(local_prop_name == NULL) {
// error
} else if(strcmp(local_prop_name, "replace_lrm") == 0) {
replace_lrm = TRUE;
any_updates = TRUE;
} else if(strcmp(local_prop_name, "source") == 0) {
source = local_prop_value;
} else if(strcmp(local_prop_name, "state") == 0) {
state = local_prop_value;
} else {
any_updates = TRUE;
set_xml_property_copy(target,
local_prop_name,
local_prop_value);
}
prop_iter = prop_iter->next;
}
unclean = xmlGetProp(target, "unclean");
exp_state = xmlGetProp(target, "exp_state");
if(safe_str_eq(state, old_state)){
// do nothing
} else if(safe_str_eq(state, "down")) {
any_updates = TRUE;
if(safe_str_neq(exp_state, "down")) {
// TODO: Only if not set?
if(old_unclean == NULL) {
time_t now = time(NULL);
char *now_s = crm_itoa((int)now);
set_xml_property_copy(target, "unclean", now_s);
crm_free(now_s);
// unset "shutdown"
set_xml_property_copy(target, "shutdown", NULL);
}
} else {
// unset "unclean"
set_xml_property_copy(target, "unclean", NULL);
}
+ } else if(safe_str_eq(state, "active")
+ && safe_str_eq(exp_state, "active")) {
+
+ // unset "unclean"
+ any_updates = TRUE;
+ set_xml_property_copy(target, "unclean", NULL);
+
} else if(state != NULL) {
any_updates = TRUE;
}
if(replace_lrm) {
xmlNodePtr lrm = find_xml_node(target, "lrm");
xmlUnlinkNode(lrm);
free_xml(lrm);
}
set_xml_property_copy(target, "state", state);
if(any_updates) {
set_node_tstamp(target);
set_xml_property_copy(target, "source", source);
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Dec 23, 12:05 PM (1 d, 8 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1128302
Default Alt Text
(13 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment