Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F7631653
incarnation.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
19 KB
Referenced Files
None
Subscribers
None
incarnation.c
View Options
/* $Id: incarnation.c,v 1.30 2005/06/29 16:40:55 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 <pengine.h>
#include <pe_utils.h>
#include <crm/msg_xml.h>
extern gboolean rsc_colocation_new(
const char *id, enum con_strength strength,
resource_t *rsc_lh, resource_t *rsc_rh);
typedef struct incarnation_variant_data_s
{
resource_t *self;
int incarnation_max;
int incarnation_max_node;
int active_incarnation;
gboolean interleave;
gboolean ordered;
GListPtr child_list; /* resource_t* */
gboolean child_starting;
gboolean child_stopping;
} incarnation_variant_data_t;
void child_stopping_constraints(
incarnation_variant_data_t *incarnation_data, enum pe_ordering type,
resource_t *child, resource_t *last, pe_working_set_t *data_set);
void child_starting_constraints(
incarnation_variant_data_t *incarnation_data, enum pe_ordering type,
resource_t *child, resource_t *last, pe_working_set_t *data_set);
#define get_incarnation_variant_data(data, rsc) \
if(rsc->variant == pe_incarnation) { \
data = (incarnation_variant_data_t *)rsc->variant_opaque; \
} else { \
pe_err("Resource %s was not an \"incarnation\" variant", \
rsc->id); \
return; \
}
void incarnation_unpack(resource_t *rsc, pe_working_set_t *data_set)
{
int lpc = 0;
crm_data_t * xml_obj_child = NULL;
crm_data_t * xml_obj = rsc->xml;
crm_data_t * xml_self = create_xml_node(NULL, XML_CIB_TAG_RESOURCE);
incarnation_variant_data_t *incarnation_data = NULL;
resource_t *self = NULL;
char *inc_max = NULL;
const char *ordered =
crm_element_value(xml_obj, XML_RSC_ATTR_ORDERED);
const char *interleave =
crm_element_value(xml_obj, XML_RSC_ATTR_INTERLEAVE);
const char *max_incarn =
get_rsc_param(rsc, XML_RSC_ATTR_INCARNATION_MAX);
const char *max_incarn_node =
get_rsc_param(rsc, XML_RSC_ATTR_INCARNATION_NODEMAX);
crm_debug_3("Processing resource %s...", rsc->id);
crm_malloc0(incarnation_data, sizeof(incarnation_variant_data_t));
incarnation_data->child_list = NULL;
incarnation_data->interleave = FALSE;
incarnation_data->ordered = FALSE;
incarnation_data->active_incarnation = 0;
incarnation_data->incarnation_max = crm_atoi(max_incarn, "1");
incarnation_data->incarnation_max_node = crm_atoi(max_incarn_node,"1");
/* this is a bit of a hack - but simplifies everything else */
copy_in_properties(xml_self, xml_obj);
xml_obj_child = find_xml_node(xml_obj, "resource_group", FALSE);
if(xml_obj_child == NULL) {
xml_obj_child = find_xml_node(
xml_obj, XML_CIB_TAG_RESOURCE, TRUE);
}
CRM_DEV_ASSERT(xml_obj_child != NULL);
if(crm_assert_failed) { return; }
xml_obj_child = copy_xml(xml_obj_child);
if(common_unpack(xml_self, &self, data_set)) {
incarnation_data->self = self;
} else {
crm_log_xml_err(xml_self, "Couldnt unpack dummy child");
return;
}
if(crm_is_true(interleave)) {
incarnation_data->interleave = TRUE;
}
if(crm_is_true(ordered)) {
incarnation_data->ordered = TRUE;
}
inherit_parent_attributes(xml_self, xml_obj_child, FALSE);
inc_max = crm_itoa(incarnation_data->incarnation_max);
for(lpc = 0; lpc < incarnation_data->incarnation_max; lpc++) {
resource_t *child_rsc = NULL;
crm_data_t * child_copy = copy_xml(xml_obj_child);
set_id(child_copy, rsc->id, lpc);
if(common_unpack(child_copy, &child_rsc, data_set)) {
char *inc_num = crm_itoa(lpc);
incarnation_data->child_list = g_list_append(
incarnation_data->child_list, child_rsc);
add_rsc_param(
child_rsc, XML_RSC_ATTR_INCARNATION, inc_num);
add_rsc_param(
child_rsc, XML_RSC_ATTR_INCARNATION_MAX, inc_max);
crm_action_debug_3(
print_resource("Added", child_rsc, FALSE));
crm_free(inc_num);
} else {
pe_err("Failed unpacking resource %s",
crm_element_value(child_copy, XML_ATTR_ID));
}
}
crm_free(inc_max);
free_xml(xml_obj_child);
crm_debug_3("Added %d children to resource %s...",
incarnation_data->incarnation_max, rsc->id);
rsc->variant_opaque = incarnation_data;
}
resource_t *
incarnation_find_child(resource_t *rsc, const char *id)
{
incarnation_variant_data_t *incarnation_data = NULL;
if(rsc->variant == pe_incarnation) {
incarnation_data = (incarnation_variant_data_t *)rsc->variant_opaque;
} else {
pe_err("Resource %s was not a \"incarnation\" variant", rsc->id);
return NULL;
}
return pe_find_resource(incarnation_data->child_list, id);
}
int incarnation_num_allowed_nodes(resource_t *rsc)
{
int num_nodes = 0;
incarnation_variant_data_t *incarnation_data = NULL;
if(rsc->variant == pe_incarnation) {
incarnation_data = (incarnation_variant_data_t *)rsc->variant_opaque;
} else {
pe_err("Resource %s was not an \"incarnation\" variant",
rsc->id);
return 0;
}
/* what *should* we return here? */
slist_iter(
child_rsc, resource_t, incarnation_data->child_list, lpc,
int tmp_num_nodes = child_rsc->fns->num_allowed_nodes(child_rsc);
if(tmp_num_nodes > num_nodes) {
num_nodes = tmp_num_nodes;
}
);
return num_nodes;
}
void incarnation_color(resource_t *rsc, pe_working_set_t *data_set)
{
int lpc = 0, lpc2 = 0, max_nodes = 0;
resource_t *child_0 = NULL;
resource_t *child_lh = NULL;
resource_t *child_rh = NULL;
incarnation_variant_data_t *incarnation_data = NULL;
get_incarnation_variant_data(incarnation_data, rsc);
child_0 = g_list_nth_data(incarnation_data->child_list, 0);
max_nodes = rsc->fns->num_allowed_nodes(rsc);
/* generate up to max_nodes * incarnation_node_max constraints */
lpc = 0;
crm_info("Distributing %d incarnations over %d nodes",
incarnation_data->incarnation_max, max_nodes);
for(; lpc < max_nodes && lpc < incarnation_data->incarnation_max; lpc++) {
child_lh = child_0;
incarnation_data->active_incarnation++;
if(lpc != 0) {
child_rh = g_list_nth_data(incarnation_data->child_list, lpc);
crm_debug_4("Incarnation %d will run on a differnt node to 0",
lpc);
rsc_colocation_new("pe_incarnation_internal_must_not",
pecs_must_not, child_lh, child_rh);
} else {
child_rh = child_0;
}
child_lh = child_rh;
for(lpc2 = 1; lpc2 < incarnation_data->incarnation_max_node; lpc2++) {
int offset = lpc + (lpc2 * max_nodes);
if(offset >= incarnation_data->incarnation_max) {
break;
}
crm_debug_4("Incarnation %d will run on the same node as %d",
offset, lpc);
incarnation_data->active_incarnation++;
child_rh = g_list_nth_data(
incarnation_data->child_list, offset);
rsc_colocation_new("pe_incarnation_internal_must",
pecs_must, child_lh, child_rh);
}
}
slist_iter(
child_rsc, resource_t, incarnation_data->child_list, lpc,
if(lpc < incarnation_data->active_incarnation) {
crm_debug_4("Coloring Incarnation %d", lpc);
child_rsc->fns->color(child_rsc, data_set);
} else {
/* TODO: assign "no color"? Doesnt seem to need it */
pe_warn("Incarnation %d cannot be started", lpc+1);
/* native_assign_color(child_rsc, data_set->no_color); */
}
);
crm_info("%d Incarnations are active", incarnation_data->active_incarnation);
}
void incarnation_update_pseudo_status(resource_t *parent, resource_t *child);
void incarnation_create_actions(resource_t *rsc, pe_working_set_t *data_set)
{
action_t *op = NULL;
resource_t *last_start_rsc = NULL;
resource_t *last_stop_rsc = NULL;
incarnation_variant_data_t *incarnation_data = NULL;
get_incarnation_variant_data(incarnation_data, rsc);
slist_iter(
child_rsc, resource_t, incarnation_data->child_list, lpc,
child_rsc->fns->create_actions(child_rsc, data_set);
incarnation_update_pseudo_status(rsc, child_rsc);
if(child_rsc->starting) {
last_start_rsc = child_rsc;
}
if(child_rsc->stopping) {
last_stop_rsc = child_rsc;
}
);
op = start_action(incarnation_data->self, NULL,
!incarnation_data->child_starting);
op->pseudo = TRUE;
op = custom_action(incarnation_data->self, started_key(rsc),
CRMD_ACTION_STARTED, NULL,
!incarnation_data->child_starting, data_set);
op->pseudo = TRUE;
child_starting_constraints(
incarnation_data, pe_ordering_optional,
NULL, last_start_rsc, data_set);
op = stop_action(incarnation_data->self, NULL,
!incarnation_data->child_stopping);
op->pseudo = TRUE;
op = custom_action(incarnation_data->self, stopped_key(rsc),
CRMD_ACTION_STOPPED, NULL,
!incarnation_data->child_stopping, data_set);
op->pseudo = TRUE;
child_stopping_constraints(
incarnation_data, pe_ordering_optional,
NULL, last_stop_rsc, data_set);
}
void
incarnation_update_pseudo_status(resource_t *parent, resource_t *child)
{
incarnation_variant_data_t *incarnation_data = NULL;
get_incarnation_variant_data(incarnation_data, parent);
if(incarnation_data->child_stopping
&& incarnation_data->child_starting) {
return;
}
slist_iter(
action, action_t, child->actions, lpc,
if(action->optional) {
continue;
}
if(safe_str_eq(CRMD_ACTION_STOP, action->task)) {
incarnation_data->child_stopping = TRUE;
} else if(safe_str_eq(CRMD_ACTION_START, action->task)) {
incarnation_data->child_starting = TRUE;
}
);
}
void
child_starting_constraints(
incarnation_variant_data_t *incarnation_data, enum pe_ordering type,
resource_t *child, resource_t *last, pe_working_set_t *data_set)
{
if(incarnation_data->ordered
|| incarnation_data->self->restart_type == pe_restart_restart) {
type = pe_ordering_manditory;
}
if(child == NULL) {
if(incarnation_data->ordered && last != NULL) {
crm_debug_4("Ordered version (last node)");
/* last child start before global started */
custom_action_order(
last, start_key(last), NULL,
incarnation_data->self, started_key(incarnation_data->self), NULL,
type, data_set);
}
} else if(incarnation_data->ordered) {
crm_debug_4("Ordered version");
if(last == NULL) {
/* global start before first child start */
last = incarnation_data->self;
} /* else: child/child relative start */
order_start_start(last, child, type);
} else {
crm_debug_4("Un-ordered version");
/* child start before global started */
custom_action_order(
child, start_key(child), NULL,
incarnation_data->self, started_key(incarnation_data->self), NULL,
type, data_set);
/* global start before child start */
/* order_start_start(incarnation_data->self, child, type); */
order_start_start(
incarnation_data->self, child, pe_ordering_manditory);
}
}
void
child_stopping_constraints(
incarnation_variant_data_t *incarnation_data, enum pe_ordering type,
resource_t *child, resource_t *last, pe_working_set_t *data_set)
{
if(incarnation_data->ordered
|| incarnation_data->self->restart_type == pe_restart_restart) {
type = pe_ordering_manditory;
}
if(child == NULL) {
if(incarnation_data->ordered && last != NULL) {
crm_debug_4("Ordered version (last node)");
/* global stop before first child stop */
order_stop_stop(incarnation_data->self, last,
pe_ordering_manditory);
}
} else if(incarnation_data->ordered && last != NULL) {
crm_debug_4("Ordered version");
/* child/child relative stop */
order_stop_stop(child, last, type);
} else if(incarnation_data->ordered) {
crm_debug_4("Ordered version (1st node)");
/* first child stop before global stopped */
custom_action_order(
child, stop_key(child), NULL,
incarnation_data->self, stopped_key(incarnation_data->self), NULL,
type, data_set);
} else {
crm_debug_4("Un-ordered version");
/* child stop before global stopped */
custom_action_order(
child, stop_key(child), NULL,
incarnation_data->self, stopped_key(incarnation_data->self), NULL,
type, data_set);
/* global stop before child stop */
order_stop_stop(incarnation_data->self, child, type);
}
}
void
incarnation_internal_constraints(resource_t *rsc, pe_working_set_t *data_set)
{
resource_t *last_rsc = NULL;
incarnation_variant_data_t *incarnation_data = NULL;
get_incarnation_variant_data(incarnation_data, rsc);
/* global stopped before start */
custom_action_order(
incarnation_data->self, stopped_key(incarnation_data->self), NULL,
incarnation_data->self, start_key(incarnation_data->self), NULL,
pe_ordering_manditory, data_set);
slist_iter(
child_rsc, resource_t, incarnation_data->child_list, lpc,
/* child stop before start */
order_restart(child_rsc);
child_starting_constraints(
incarnation_data, pe_ordering_optional,
child_rsc, last_rsc, data_set);
child_stopping_constraints(
incarnation_data, pe_ordering_optional,
child_rsc, last_rsc, data_set);
last_rsc = child_rsc;
);
}
void incarnation_rsc_colocation_lh(rsc_colocation_t *constraint)
{
gboolean do_interleave = FALSE;
resource_t *rsc = constraint->rsc_lh;
incarnation_variant_data_t *incarnation_data = NULL;
incarnation_variant_data_t *incarnation_data_rh = NULL;
if(rsc == NULL) {
pe_err("rsc_lh was NULL for %s", constraint->id);
return;
} else if(constraint->rsc_rh == NULL) {
pe_err("rsc_rh was NULL for %s", constraint->id);
return;
} else if(constraint->strength != pecs_must_not) {
pe_warn("rsc_colocations other than \"-INFINITY\" "
"are not supported for incarnation resources");
return;
} else {
crm_debug_4("Processing constraints from %s", rsc->id);
}
get_incarnation_variant_data(incarnation_data, rsc);
if(constraint->rsc_lh == constraint->rsc_rh) {
do_interleave = TRUE;
get_incarnation_variant_data(
incarnation_data_rh, constraint->rsc_rh);
} else if(constraint->rsc_rh->variant == pe_incarnation) {
get_incarnation_variant_data(
incarnation_data_rh, constraint->rsc_rh);
if(incarnation_data->interleave == FALSE) {
} else if(incarnation_data_rh->interleave == FALSE) {
} else if(incarnation_data->incarnation_max
== incarnation_data_rh->incarnation_max) {
do_interleave = TRUE;
}
}
if(do_interleave) {
resource_t *child_lh = NULL;
resource_t *child_rh = NULL;
resource_t *parent_rh = constraint->rsc_rh;
GListPtr iter_lh = incarnation_data->child_list;
GListPtr iter_rh = incarnation_data_rh->child_list;
while(iter_lh != NULL && iter_rh != NULL) {
child_lh = iter_lh->data;
child_rh = iter_rh->data;
iter_lh = iter_lh->next;
iter_rh = iter_rh->next;
constraint->rsc_rh = child_rh;
child_rh->fns->rsc_colocation_rh(child_lh, constraint);
}
constraint->rsc_rh = parent_rh;
return;
}
slist_iter(
child_rsc, resource_t, incarnation_data->child_list, lpc,
crm_action_debug_3(print_resource("LHS", child_rsc, TRUE));
child_rsc->fns->rsc_colocation_rh(child_rsc, constraint);
);
}
void incarnation_rsc_colocation_rh(resource_t *rsc, rsc_colocation_t *constraint)
{
incarnation_variant_data_t *incarnation_data = NULL;
crm_debug_3("Processing RH of constraint %s", constraint->id);
if(rsc == NULL) {
pe_err("rsc_lh was NULL for %s", constraint->id);
return;
} else if(constraint->rsc_rh == NULL) {
pe_err("rsc_rh was NULL for %s", constraint->id);
return;
} else if(constraint->strength != pecs_must_not) {
pe_warn("rsc_dependencies other than \"must_not\" "
"are not supported for incarnation resources");
return;
} else {
crm_action_debug_3(print_resource("LHS", rsc, FALSE));
}
get_incarnation_variant_data(incarnation_data, rsc);
slist_iter(
child_rsc, resource_t, incarnation_data->child_list, lpc,
crm_action_debug_3(print_resource("RHS", child_rsc, FALSE));
child_rsc->fns->rsc_colocation_rh(child_rsc, constraint);
);
}
void incarnation_rsc_order_lh(resource_t *rsc, order_constraint_t *order)
{
char *stop_id = NULL;
char *start_id = NULL;
incarnation_variant_data_t *incarnation_data = NULL;
get_incarnation_variant_data(incarnation_data, rsc);
crm_debug_3("Processing LH of ordering constraint %d", order->id);
stop_id = stop_key(rsc);
start_id = start_key(rsc);
if(safe_str_eq(order->lh_action_task, start_id)) {
crm_free(order->lh_action_task);
order->lh_action_task = started_key(rsc);
} else if(safe_str_eq(order->lh_action_task, stop_id)) {
crm_free(order->lh_action_task);
order->lh_action_task = stopped_key(rsc);
}
crm_free(start_id);
crm_free(stop_id);
incarnation_data->self->fns->rsc_order_lh(incarnation_data->self, order);
}
void incarnation_rsc_order_rh(
action_t *lh_action, resource_t *rsc, order_constraint_t *order)
{
incarnation_variant_data_t *incarnation_data = NULL;
get_incarnation_variant_data(incarnation_data, rsc);
crm_debug_3("Processing RH of ordering constraint %d", order->id);
incarnation_data->self->fns->rsc_order_rh(lh_action, incarnation_data->self, order);
}
void incarnation_rsc_location(resource_t *rsc, rsc_to_node_t *constraint)
{
incarnation_variant_data_t *incarnation_data = NULL;
get_incarnation_variant_data(incarnation_data, rsc);
crm_debug_3("Processing actions from %s", rsc->id);
incarnation_data->self->fns->rsc_location(incarnation_data->self, constraint);
slist_iter(
child_rsc, resource_t, incarnation_data->child_list, lpc,
child_rsc->fns->rsc_location(child_rsc, constraint);
);
}
void incarnation_expand(resource_t *rsc, pe_working_set_t *data_set)
{
incarnation_variant_data_t *incarnation_data = NULL;
get_incarnation_variant_data(incarnation_data, rsc);
crm_debug_3("Processing actions from %s", rsc->id);
incarnation_data->self->fns->expand(incarnation_data->self, data_set);
slist_iter(
child_rsc, resource_t, incarnation_data->child_list, lpc,
child_rsc->fns->expand(child_rsc, data_set);
);
}
void incarnation_printw(resource_t *rsc, const char *pre_text, int *index)
{
#ifdef HAVE_LIBNCURSES
const char *child_text = NULL;
incarnation_variant_data_t *incarnation_data = NULL;
get_incarnation_variant_data(incarnation_data, rsc);
if(pre_text != NULL) {
child_text = " ";
} else {
child_text = " ";
}
move(*index, 0);
printw("Incarnation: %s\n", rsc->id);
slist_iter(
child_rsc, resource_t, incarnation_data->child_list, lpc,
(*index)++;
child_rsc->fns->printw(child_rsc, child_text, index);
);
#else
crm_err("printw support requires ncurses to be available during configure");
#endif
}
void incarnation_dump(resource_t *rsc, const char *pre_text, gboolean details)
{
incarnation_variant_data_t *incarnation_data = NULL;
get_incarnation_variant_data(incarnation_data, rsc);
common_dump(rsc, pre_text, details);
incarnation_data->self->fns->dump(
incarnation_data->self, pre_text, details);
slist_iter(
child_rsc, resource_t, incarnation_data->child_list, lpc,
child_rsc->fns->dump(child_rsc, pre_text, details);
);
}
void incarnation_free(resource_t *rsc)
{
incarnation_variant_data_t *incarnation_data = NULL;
get_incarnation_variant_data(incarnation_data, rsc);
crm_debug_3("Freeing %s", rsc->id);
slist_iter(
child_rsc, resource_t, incarnation_data->child_list, lpc,
crm_debug_3("Freeing child %s", child_rsc->id);
free_xml(child_rsc->xml);
child_rsc->fns->free(child_rsc);
);
crm_debug_3("Freeing child list");
pe_free_shallow_adv(incarnation_data->child_list, FALSE);
free_xml(incarnation_data->self->xml);
incarnation_data->self->fns->free(incarnation_data->self);
common_free(rsc);
}
void
incarnation_agent_constraints(resource_t *rsc)
{
incarnation_variant_data_t *incarnation_data = NULL;
get_incarnation_variant_data(incarnation_data, rsc);
slist_iter(
child_rsc, resource_t, incarnation_data->child_list, lpc,
child_rsc->fns->agent_constraints(child_rsc);
);
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Thu, Oct 16, 3:05 PM (16 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2530229
Default Alt Text
incarnation.c (19 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment