22 #include <sys/types.h>    63         .match_data = match_data,
    96         .match_data = match_data,
   107     const char *tag = NULL;
   108     const char *attr = NULL;
   111     tag = crm_element_name(expr);
   134 #if ENABLE_VERSIONED_ATTRS   163     uint32_t epact, diy, goldn;
   168     goldn = (y % 19) + 1;
   169     epact = (11 * goldn + 18) % 30;
   170     if ((epact == 25 && goldn > 11) || epact == 24)
   173     return ((((((diy + epact) * 6) + 11) % 177) / 22) & 7);
   177 check_one(xmlNode *cron_spec, 
const char *xml_field, uint32_t time_field) {
   189     } 
else if (low == high) {
   191         if (time_field < low) {
   193         } 
else if (time_field > high) {
   198     } 
else if (low != -1 && high != -1) {
   200         if (time_field < low) {
   202         } 
else if (time_field > high) {
   207     } 
else if (low == -1) {
   210     } 
else if (high == -1) {
   217         crm_debug(
"Condition '%s' in %s: passed", value, xml_field);
   219         crm_debug(
"Condition '%s' in %s: failed", value, xml_field);
   226 check_passes(
int rc) {
   235 #define CHECK_ONE(spec, name, var) do { \   236     int subpart_rc = check_one(spec, name, var); \   237     if (check_passes(subpart_rc) == FALSE) { \   245     uint32_t h, m, s, y, d, w;
   267     CHECK_ONE(cron_spec, 
"moon", phase_of_the_moon(now));
   277 update_field(
crm_time_t *t, xmlNode *xml, 
const char *attr,
   283         && (value != 0LL) && (value >= INT_MIN) && (value <= INT_MAX)) {
   284         time_fn(t, (
int) value);
   310     if ((next_change != NULL) && (t != NULL)) {
   319 typedef struct sorted_set_s {
   322     const char *special_name;   
   327 sort_pairs(gconstpointer a, gconstpointer b)
   332     if (a == NULL && b == NULL) {
   334     } 
else if (a == NULL) {
   336     } 
else if (b == NULL) {
   340     if (pcmk__str_eq(pair_a->name, pair_a->special_name, 
pcmk__str_casei)) {
   343     } 
else if (pcmk__str_eq(pair_b->name, pair_a->special_name, 
pcmk__str_casei)) {
   347     if (pair_a->score < pair_b->score) {
   349     } 
else if (pair_a->score > pair_b->score) {
   356 populate_hash(xmlNode * nvpair_list, GHashTable * hash, gboolean overwrite, xmlNode * top)
   358     const char *
name = NULL;
   359     const char *value = NULL;
   360     const char *old_value = NULL;
   361     xmlNode *list = nvpair_list;
   362     xmlNode *an_attr = NULL;
   364     name = crm_element_name(list->children);
   366         list = list->children;
   369     for (an_attr = pcmk__xe_first_child(list); an_attr != NULL;
   370          an_attr = pcmk__xe_next(an_attr)) {
   385             if (
name == NULL || value == NULL) {
   389             old_value = g_hash_table_lookup(hash, 
name);
   393                     crm_trace(
"Letting %s default (removing explicit value \"%s\")",
   395                     g_hash_table_remove(hash, 
name);
   399             } 
else if (old_value == NULL) {
   401                 g_hash_table_insert(hash, strdup(
name), strdup(value));
   403             } 
else if (overwrite) {
   404                 crm_trace(
"Setting %s=\"%s\" (overwriting old value \"%s\")",
   405                           name, value, old_value);
   406                 g_hash_table_replace(hash, strdup(
name), strdup(value));
   412 #if ENABLE_VERSIONED_ATTRS   414 get_versioned_rule(xmlNode * attr_set)
   416     xmlNode * rule = NULL;
   417     xmlNode * expr = NULL;
   419     for (rule = pcmk__xe_first_child(attr_set); rule != NULL;
   420          rule = pcmk__xe_next(rule)) {
   422         if (pcmk__str_eq((
const char *)rule->name, 
XML_TAG_RULE,
   424             for (expr = pcmk__xe_first_child(rule); expr != NULL;
   425                  expr = pcmk__xe_next(expr)) {
   438 add_versioned_attributes(xmlNode * attr_set, xmlNode * versioned_attrs)
   440     xmlNode *attr_set_copy = NULL;
   441     xmlNode *rule = NULL;
   442     xmlNode *expr = NULL;
   444     if (!attr_set || !versioned_attrs) {
   450     rule = get_versioned_rule(attr_set_copy);
   456     expr = pcmk__xe_first_child(rule);
   457     while (expr != NULL) {
   459             xmlNode *node = expr;
   461             expr = pcmk__xe_next(expr);
   464             expr = pcmk__xe_next(expr);
   472 typedef struct unpack_data_s {
   481 unpack_attr_set(gpointer 
data, gpointer user_data)
   487                        unpack_data->next_change)) {
   491 #if ENABLE_VERSIONED_ATTRS   492     if (get_versioned_rule(pair->attr_set) && !(unpack_data->rule_data->node_hash &&
   493         g_hash_table_lookup_extended(unpack_data->rule_data->node_hash,
   500     crm_trace(
"Adding attributes from %s (score %d) %s overwrite",
   501               pair->name, pair->score,
   502               (unpack_data->overwrite? 
"with" : 
"without"));
   503     populate_hash(pair->attr_set, unpack_data->hash, unpack_data->overwrite, unpack_data->top);
   506 #if ENABLE_VERSIONED_ATTRS   508 unpack_versioned_attr_set(gpointer 
data, gpointer user_data)
   514                       unpack_data->next_change)) {
   515         add_versioned_attributes(pair->attr_set, unpack_data->hash);
   532 make_pairs(xmlNode *top, xmlNode *xml_obj, 
const char *set_name,
   533            const char *always_first)
   535     GList *unsorted = NULL;
   537     if (xml_obj == NULL) {
   540     for (xmlNode *attr_set = pcmk__xe_first_child(xml_obj); attr_set != NULL;
   541          attr_set = pcmk__xe_next(attr_set)) {
   543         if (pcmk__str_eq(set_name, (
const char *) attr_set->name,
   545             const char *score = NULL;
   547             xmlNode *expanded_attr_set = 
expand_idref(attr_set, top);
   549             if (expanded_attr_set == NULL) {
   555             pair->name = 
ID(expanded_attr_set);
   556             pair->special_name = always_first;
   557             pair->attr_set = expanded_attr_set;
   562             unsorted = g_list_prepend(unsorted, pair);
   565     return g_list_sort(unsorted, sort_pairs);
   583 unpack_nvpair_blocks(xmlNode *top, xmlNode *xml_obj, 
const char *set_name,
   584                      void *hash, 
const char *always_first, gboolean overwrite,
   588     GList *pairs = make_pairs(top, xml_obj, set_name, always_first);
   593             .overwrite = overwrite,
   594             .next_change = next_change,
   596             .rule_data = rule_data
   599         g_list_foreach(pairs, unpack_func, &
data);
   600         g_list_free_full(pairs, free);
   607                 const char *always_first, gboolean overwrite,
   610     unpack_nvpair_blocks(top, xml_obj, set_name, hash, always_first,
   611                          overwrite, rule_data, next_change, unpack_attr_set);
   629                   GHashTable *node_hash, GHashTable *hash,
   630                   const char *always_first, gboolean overwrite,
   643                     always_first, overwrite, next_change);
   646 #if ENABLE_VERSIONED_ATTRS   648 pe_eval_versioned_attributes(xmlNode *top, xmlNode *xml_obj, 
const char *set_name,
   652     unpack_nvpair_blocks(top, xml_obj, set_name, hash, NULL, FALSE, rule_data,
   653                          next_change, unpack_versioned_attr_set);
   662     const char *p, *last_match_index;
   663     char *p_dst, *result = NULL;
   665     if (pcmk__str_empty(
string) || !match_data) {
   669     p = last_match_index = string;
   672         if (*p == 
'%' && *(p + 1) && isdigit(*(p + 1))) {
   674             if (match_data->
nregs >= i && match_data->
pmatch[i].rm_so != -1 &&
   675                 match_data->
pmatch[i].rm_eo > match_data->
pmatch[i].rm_so) {
   676                 len += p - last_match_index + (match_data->
pmatch[i].rm_eo - match_data->
pmatch[i].rm_so);
   677                 last_match_index = p + 2;
   683     len += p - last_match_index + 1;
   690     p_dst = result = calloc(1, len);
   694         if (*p == 
'%' && *(p + 1) && isdigit(*(p + 1))) {
   696             if (match_data->
nregs >= i && match_data->
pmatch[i].rm_so != -1 &&
   697                 match_data->
pmatch[i].rm_eo > match_data->
pmatch[i].rm_so) {
   699                 int match_len = match_data->
pmatch[i].rm_eo - match_data->
pmatch[i].rm_so;
   700                 memcpy(p_dst, match_data->
string + match_data->
pmatch[i].rm_so, match_len);
   714 #if ENABLE_VERSIONED_ATTRS   716 pe_unpack_versioned_parameters(xmlNode *versioned_params, 
const char *ra_version)
   720     if (versioned_params && ra_version) {
   722         xmlNode *attr_set = pcmk__xe_first_child(versioned_params);
   728                               crm_element_name(attr_set), node_hash, hash, NULL,
   732         g_hash_table_destroy(node_hash);
   743     gboolean ruleset_default = TRUE;
   748         ruleset_default = FALSE;
   760     return ruleset_default;
   766     xmlNode *expr = NULL;
   767     gboolean test = TRUE;
   768     gboolean empty = TRUE;
   769     gboolean passed = TRUE;
   770     gboolean do_and = TRUE;
   771     const char *value = NULL;
   781     for (expr = pcmk__xe_first_child(rule); expr != NULL;
   782          expr = pcmk__xe_next(expr)) {
   787         if (test && do_and == FALSE) {
   791         } 
else if (test == FALSE && do_and) {
   798         crm_err(
"Invalid Rule %s: rules must contain at least one expression", 
ID(rule));
   801     crm_trace(
"Rule %s %s", 
ID(rule), passed ? 
"passed" : 
"failed");
   808     gboolean accept = FALSE;
   809     const char *
uname = NULL;
   850 #if ENABLE_VERSIONED_ATTRS   853                 g_hash_table_lookup_extended(rule_data->
node_hash,
   872               ID(expr), accept ? 
"passed" : 
"failed", 
uname ? 
uname : 
"all nodes");
   892 compare_attr_expr_vals(
const char *l_val, 
const char *r_val, 
const char *
type,
   897     if (l_val != NULL && r_val != NULL) {
   909             crm_trace(
"Defaulting to %s based comparison for '%s' op", 
type, op);
   913             cmp = strcasecmp(l_val, r_val);
   923                 if (l_val_num < r_val_num) {
   925                 } 
else if (l_val_num > r_val_num) {
   932                 crm_debug(
"Integer parse error. Comparing %s and %s as strings",
   934                 cmp = compare_attr_expr_vals(l_val, r_val, 
"string", op);
   945                 if (l_val_num < r_val_num) {
   947                 } 
else if (l_val_num > r_val_num) {
   954                 crm_debug(
"Floating-point parse error. Comparing %s and %s as "   955                           "strings", l_val, r_val);
   956                 cmp = compare_attr_expr_vals(l_val, r_val, 
"string", op);
   964     } 
else if (l_val == NULL && r_val == NULL) {
   966     } 
else if (r_val == NULL) {
   990 accept_attr_expr(
const char *l_val, 
const char *r_val, 
const char *
type,
   996         return (l_val != NULL);
   999         return (l_val == NULL);
  1003     cmp = compare_attr_expr_vals(l_val, r_val, 
type, op);
  1011     } 
else if (l_val == NULL || r_val == NULL) {
  1040 expand_value_source(
const char *value, 
const char *value_source,
  1043     GHashTable *table = NULL;
  1045     if (pcmk__str_empty(value)) {
  1049         table = match_data->
params;
  1052         table = match_data->
meta;
  1058     if (table == NULL) {
  1061     return (
const char *) g_hash_table_lookup(table, value);
  1077     gboolean attr_allocated = FALSE;
  1078     const char *h_val = NULL;
  1080     const char *op = NULL;
  1081     const char *
type = NULL;
  1082     const char *attr = NULL;
  1083     const char *value = NULL;
  1084     const char *value_source = NULL;
  1092     if (attr == NULL || op == NULL) {
  1093         pe_err(
"Invalid attribute or operation in expression"  1103             if (resolved_attr != NULL) {
  1104                 attr = (
const char *) resolved_attr;
  1105                 attr_allocated = TRUE;
  1110         value = expand_value_source(value, value_source, rule_data->
match_data);
  1114         h_val = (
const char *)g_hash_table_lookup(rule_data->
node_hash, attr);
  1117     if (attr_allocated) {
  1122     return accept_attr_expr(h_val, value, 
type, op);
  1140     const char *value = NULL;
  1143     xmlNode *duration_spec = NULL;
  1144     xmlNode *date_spec = NULL;
  1155     if (value != NULL) {
  1159     if (value != NULL) {
  1163     if (start != NULL && end == NULL && duration_spec != NULL) {
  1168         if ((start == NULL) && (end == NULL)) {
  1172             crm_time_set_if_earlier(next_change, start);
  1177             if (end && next_change) {
  1180                 crm_time_set_if_earlier(next_change, end);
  1189         if (start == NULL) {
  1198             crm_time_set_if_earlier(next_change, start);
  1206             crm_time_set_if_earlier(next_change, end);
  1223     crm_trace(
"Testing op_defaults expression: %s", 
ID(expr));
  1225     if (rule_data->
op_data == NULL) {
  1226         crm_trace(
"No operations data provided");
  1231     if (interval == 0 && errno != 0) {
  1232         crm_trace(
"Could not parse interval: %s", interval_s);
  1261     gboolean accept = FALSE;
  1262     const char *op = NULL;
  1263     const char *value = NULL;
  1308     crm_trace(
"Testing rsc_defaults expression: %s", 
ID(expr));
  1315     if (
class != NULL &&
  1351     return pe_test_rule(rule, node_hash, role, now, NULL, NULL);
  1358                                     .
re = re_match_data,
  1362     return pe_test_rule(rule, node_hash, role, now, NULL, &match_data);
  1369     return pe_test_rule(rule, node_hash, role, now, NULL, match_data);
  1382                                     .
re = re_match_data,
  1399                            GHashTable *node_hash, GHashTable *hash,
  1400                            const char *always_first, gboolean overwrite,
  1412     unpack_nvpair_blocks(top, xml_obj, set_name, hash, always_first,
  1413                          overwrite, &rule_data, NULL, unpack_attr_set);
 crm_time_t * crm_time_new_undefined(void)
Allocate memory for an uninitialized time object. 
 
#define CRM_CHECK(expr, failure_action)
 
void crm_time_add_years(crm_time_t *dt, int value)
 
gboolean pe_test_rule_re(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now, pe_re_match_data_t *re_match_data)
 
Deprecated Pacemaker rule API. 
 
void crm_time_add_seconds(crm_time_t *dt, int value)
Add a given number of seconds to a date/time or duration. 
 
bool pcmk__char_in_any_str(int ch,...) G_GNUC_NULL_TERMINATED
 
#define XML_EXPR_ATTR_TYPE
 
bool crm_time_is_defined(const crm_time_t *t)
Check whether a time object has been initialized yet. 
 
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
 
struct crm_time_s crm_time_t
 
gboolean test_expression(xmlNode *expr, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now)
 
#define XML_RULE_ATTR_SCORE
 
xmlNode * first_named_child(const xmlNode *parent, const char *name)
 
int char2score(const char *score)
 
gboolean pe_test_expression_re(xmlNode *expr, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now, pe_re_match_data_t *re_match_data)
 
#define XML_LRM_ATTR_INTERVAL
 
#define XML_EXPR_ATTR_VALUE_SOURCE
 
void pe_unpack_nvpairs(xmlNode *top, xmlNode *xml_obj, const char *set_name, GHashTable *node_hash, GHashTable *hash, const char *always_first, gboolean overwrite, crm_time_t *now, crm_time_t *next_change)
Extract nvpair blocks contained by an XML element into a hash table. 
 
int crm_time_get_ordinal(crm_time_t *dt, uint32_t *y, uint32_t *d)
 
#define XML_NVPAIR_ATTR_NAME
 
#define CHECK_ONE(spec, name, var)
 
enum crm_ais_msg_types type
 
#define CRM_ATTR_RA_VERSION
 
gboolean pe_test_rule(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now, crm_time_t *next_change, pe_match_data_t *match_data)
 
#define XML_CIB_TAG_NVPAIR
 
gboolean pe_eval_rules(xmlNode *ruleset, pe_rule_eval_data_t *rule_data, crm_time_t *next_change)
 
void crm_time_add_hours(crm_time_t *dt, int value)
 
gboolean pe_test_expression_full(xmlNode *expr, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now, pe_match_data_t *match_data)
 
xmlNode * copy_xml(xmlNode *src_node)
 
pe_match_data_t * match_data
 
int pe__eval_date_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data, crm_time_t *next_change)
 
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
 
gboolean pe_test_expression(xmlNode *expr, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now, crm_time_t *next_change, pe_match_data_t *match_data)
Evaluate one rule subelement (pass/fail) 
 
pe_op_eval_data_t * op_data
 
#define crm_debug(fmt, args...)
 
gboolean pe_eval_subexpr(xmlNode *expr, pe_rule_eval_data_t *rule_data, crm_time_t *next_change)
 
void crm_time_add_weeks(crm_time_t *dt, int value)
 
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute. 
 
#define XML_EXPR_ATTR_VALUE
 
void crm_time_add_months(crm_time_t *dt, int value)
 
#define crm_trace(fmt, args...)
 
xmlNode * expand_idref(xmlNode *input, xmlNode *top)
 
#define XML_AGENT_ATTR_PROVIDER
 
Wrappers for and extensions to libxml2. 
 
char * pe_expand_re_matches(const char *string, pe_re_match_data_t *match_data)
 
void crm_time_add_minutes(crm_time_t *dt, int value)
 
#define XML_EXPR_ATTR_OPERATION
 
gboolean pe__eval_role_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
 
gboolean pe_evaluate_rules(xmlNode *ruleset, GHashTable *node_hash, crm_time_t *now, crm_time_t *next_change)
Evaluate any rules contained by given XML element. 
 
void free_xml(xmlNode *child)
 
gboolean pe_test_rule_full(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now, pe_match_data_t *match_data)
 
enum rsc_role_e text2role(const char *role)
 
int pcmk__scan_double(const char *text, double *result, const char *default_text, char **end_text)
 
pe_rsc_eval_data_t * rsc_data
 
gboolean pe_eval_expr(xmlNode *rule, pe_rule_eval_data_t *rule_data, crm_time_t *next_change)
 
#define XML_RULE_ATTR_BOOLEAN_OP
 
gboolean test_rule(xmlNode *rule, GHashTable *node_hash, enum rsc_role_e role, crm_time_t *now)
 
void populate_hash(xmlNode *nvpair_list, GHashTable *hash, const char **attrs, int attrs_length)
 
crm_time_t * pe_parse_xml_duration(crm_time_t *start, xmlNode *duration_spec)
 
struct unpack_data_s unpack_data_t
 
CRM_TRACE_INIT_DATA(pe_rules)
 
struct sorted_set_s sorted_set_t
 
void pe_eval_nvpairs(xmlNode *top, xmlNode *xml_obj, const char *set_name, pe_rule_eval_data_t *rule_data, GHashTable *hash, const char *always_first, gboolean overwrite, crm_time_t *next_change)
 
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
 
int crm_time_get_gregorian(crm_time_t *dt, uint32_t *y, uint32_t *m, uint32_t *d)
 
#define crm_err(fmt, args...)
 
int crm_time_get_timeofday(crm_time_t *dt, uint32_t *h, uint32_t *m, uint32_t *s)
 
char guint crm_parse_interval_spec(const char *input)
Parse milliseconds from a Pacemaker interval specification. 
 
gboolean pe__eval_op_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
 
gboolean test_ruleset(xmlNode *ruleset, GHashTable *node_hash, crm_time_t *now)
 
void crm_time_set(crm_time_t *target, crm_time_t *source)
 
crm_time_t * crm_time_new(const char *string)
 
int compare_version(const char *version1, const char *version2)
 
gboolean pe__eval_rsc_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
 
#define XML_NVPAIR_ATTR_VALUE
 
gboolean pe__eval_attr_expr(xmlNodePtr expr, pe_rule_eval_data_t *rule_data)
 
int crm_time_compare(crm_time_t *dt, crm_time_t *rhs)
 
rsc_role_e
Possible roles that a resource can be in. 
 
int add_node_nocopy(xmlNode *parent, const char *name, xmlNode *child)
 
int pcmk__parse_ll_range(const char *srcstring, long long *start, long long *end)
 
void unpack_instance_attributes(xmlNode *top, xmlNode *xml_obj, const char *set_name, GHashTable *node_hash, GHashTable *hash, const char *always_first, gboolean overwrite, crm_time_t *now)
 
enum expression_type find_expression_type(xmlNode *expr)
 
int pe_cron_range_satisfied(crm_time_t *now, xmlNode *cron_spec)
 
int crm_time_get_isoweek(crm_time_t *dt, uint32_t *y, uint32_t *w, uint32_t *d)
 
#define XML_EXPR_ATTR_ATTRIBUTE
 
void crm_time_add_days(crm_time_t *dt, int value)
 
#define XML_AGENT_ATTR_CLASS
 
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag. 
 
void crm_time_free(crm_time_t *dt)