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   166         .match_data = match_data,
   194     uint32_t epact, diy, goldn;
   199     goldn = (y % 19) + 1;
   200     epact = (11 * goldn + 18) % 30;
   201     if ((epact == 25 && goldn > 11) || epact == 24)
   204     return ((((((diy + epact) * 6) + 11) % 177) / 22) & 7);
   208 check_one(xmlNode *cron_spec, 
const char *xml_field, uint32_t time_field) {
   220     } 
else if (low == high) {
   222         if (time_field < low) {
   224         } 
else if (time_field > high) {
   229     } 
else if (low != -1 && high != -1) {
   231         if (time_field < low) {
   233         } 
else if (time_field > high) {
   238     } 
else if (low == -1) {
   241     } 
else if (high == -1) {
   248         crm_debug(
"Condition '%s' in %s: passed", value, xml_field);
   250         crm_debug(
"Condition '%s' in %s: failed", value, xml_field);
   257 check_passes(
int rc) {
   266 #define CHECK_ONE(spec, name, var) do { \   267     int subpart_rc = check_one(spec, name, var); \   268     if (check_passes(subpart_rc) == FALSE) { \   276     uint32_t h, m, s, y, d, w;
   298     CHECK_ONE(cron_spec, 
"moon", phase_of_the_moon(now));
   307 #define update_field(xml_field, time_fn)            \   308     value = crm_element_value(duration_spec, xml_field);    \   309     if(value != NULL) {                     \   310     int value_i = crm_parse_int(value, "0");        \   311     time_fn(end, value_i);                  \   318     const char *value = NULL;
   370     if ((next_change != NULL) && (t != NULL)) {
   404 typedef struct sorted_set_s {
   407     const char *special_name;   
   412 sort_pairs(gconstpointer a, gconstpointer b)
   417     if (a == NULL && b == NULL) {
   419     } 
else if (a == NULL) {
   421     } 
else if (b == NULL) {
   425     if (pcmk__str_eq(pair_a->name, pair_a->special_name, 
pcmk__str_casei)) {
   428     } 
else if (pcmk__str_eq(pair_b->name, pair_a->special_name, 
pcmk__str_casei)) {
   432     if (pair_a->score < pair_b->score) {
   434     } 
else if (pair_a->score > pair_b->score) {
   441 populate_hash(xmlNode * nvpair_list, GHashTable * hash, gboolean overwrite, xmlNode * top)
   443     const char *
name = NULL;
   444     const char *value = NULL;
   445     const char *old_value = NULL;
   446     xmlNode *list = nvpair_list;
   447     xmlNode *an_attr = NULL;
   449     name = crm_element_name(list->children);
   451         list = list->children;
   454     for (an_attr = pcmk__xe_first_child(list); an_attr != NULL;
   455          an_attr = pcmk__xe_next(an_attr)) {
   470             if (
name == NULL || value == NULL) {
   474             old_value = g_hash_table_lookup(hash, 
name);
   478                     crm_trace(
"Letting %s default (removing explicit value \"%s\")",
   480                     g_hash_table_remove(hash, 
name);
   484             } 
else if (old_value == NULL) {
   486                 g_hash_table_insert(hash, strdup(
name), strdup(value));
   488             } 
else if (overwrite) {
   489                 crm_trace(
"Setting %s=\"%s\" (overwriting old value \"%s\")",
   490                           name, value, old_value);
   491                 g_hash_table_replace(hash, strdup(
name), strdup(value));
   497 #if ENABLE_VERSIONED_ATTRS   499 get_versioned_rule(xmlNode * attr_set)
   501     xmlNode * rule = NULL;
   502     xmlNode * expr = NULL;
   504     for (rule = pcmk__xe_first_child(attr_set); rule != NULL;
   505          rule = pcmk__xe_next(rule)) {
   507         if (pcmk__str_eq((
const char *)rule->name, 
XML_TAG_RULE,
   509             for (expr = pcmk__xe_first_child(rule); expr != NULL;
   510                  expr = pcmk__xe_next(expr)) {
   523 add_versioned_attributes(xmlNode * attr_set, xmlNode * versioned_attrs)
   525     xmlNode *attr_set_copy = NULL;
   526     xmlNode *rule = NULL;
   527     xmlNode *expr = NULL;
   529     if (!attr_set || !versioned_attrs) {
   535     rule = get_versioned_rule(attr_set_copy);
   541     expr = pcmk__xe_first_child(rule);
   542     while (expr != NULL) {
   544             xmlNode *node = expr;
   546             expr = pcmk__xe_next(expr);
   549             expr = pcmk__xe_next(expr);
   557 typedef struct unpack_data_s {
   566 unpack_attr_set(gpointer 
data, gpointer user_data)
   572                        unpack_data->next_change)) {
   576 #if ENABLE_VERSIONED_ATTRS   577     if (get_versioned_rule(pair->attr_set) && !(unpack_data->rule_data->node_hash &&
   578         g_hash_table_lookup_extended(unpack_data->rule_data->node_hash,
   585     crm_trace(
"Adding attributes from %s (score %d) %s overwrite",
   586               pair->name, pair->score,
   587               (unpack_data->overwrite? 
"with" : 
"without"));
   588     populate_hash(pair->attr_set, unpack_data->hash, unpack_data->overwrite, unpack_data->top);
   591 #if ENABLE_VERSIONED_ATTRS   593 unpack_versioned_attr_set(gpointer 
data, gpointer user_data)
   599                       unpack_data->next_change)) {
   600         add_versioned_attributes(pair->attr_set, unpack_data->hash);
   617 make_pairs(xmlNode *top, xmlNode *xml_obj, 
const char *set_name,
   618            const char *always_first)
   621     const char *score = NULL;
   623     xmlNode *attr_set = NULL;
   625     if (xml_obj == NULL) {
   628     for (attr_set = pcmk__xe_first_child(xml_obj); attr_set != NULL;
   629          attr_set = pcmk__xe_next(attr_set)) {
   635             if (attr_set == NULL) {
   640             pair->name = 
ID(attr_set);
   641             pair->special_name = always_first;
   642             pair->attr_set = attr_set;
   647             unsorted = g_list_prepend(unsorted, pair);
   650     return g_list_sort(unsorted, sort_pairs);
   668 unpack_nvpair_blocks(xmlNode *top, xmlNode *xml_obj, 
const char *set_name,
   669                      void *hash, 
const char *always_first, gboolean overwrite,
   673     GList *pairs = make_pairs(top, xml_obj, set_name, always_first);
   678             .overwrite = overwrite,
   679             .next_change = next_change,
   681             .rule_data = rule_data
   684         g_list_foreach(pairs, unpack_func, &
data);
   685         g_list_free_full(pairs, free);
   692                 const char *always_first, gboolean overwrite,
   695     unpack_nvpair_blocks(top, xml_obj, set_name, hash, always_first,
   696                          overwrite, rule_data, next_change, unpack_attr_set);
   714                   GHashTable *node_hash, GHashTable *hash,
   715                   const char *always_first, gboolean overwrite,
   728                     always_first, overwrite, next_change);
   731 #if ENABLE_VERSIONED_ATTRS   733 pe_eval_versioned_attributes(xmlNode *top, xmlNode *xml_obj, 
const char *set_name,
   737     unpack_nvpair_blocks(top, xml_obj, set_name, hash, NULL, FALSE, rule_data,
   738                          next_change, unpack_versioned_attr_set);
   747     const char *p, *last_match_index;
   748     char *p_dst, *result = NULL;
   750     if (pcmk__str_empty(
string) || !match_data) {
   754     p = last_match_index = string;
   757         if (*p == 
'%' && *(p + 1) && isdigit(*(p + 1))) {
   759             if (match_data->
nregs >= i && match_data->
pmatch[i].rm_so != -1 &&
   760                 match_data->
pmatch[i].rm_eo > match_data->
pmatch[i].rm_so) {
   761                 len += p - last_match_index + (match_data->
pmatch[i].rm_eo - match_data->
pmatch[i].rm_so);
   762                 last_match_index = p + 2;
   768     len += p - last_match_index + 1;
   775     p_dst = result = calloc(1, len);
   779         if (*p == 
'%' && *(p + 1) && isdigit(*(p + 1))) {
   781             if (match_data->
nregs >= i && match_data->
pmatch[i].rm_so != -1 &&
   782                 match_data->
pmatch[i].rm_eo > match_data->
pmatch[i].rm_so) {
   784                 int match_len = match_data->
pmatch[i].rm_eo - match_data->
pmatch[i].rm_so;
   785                 memcpy(p_dst, match_data->
string + match_data->
pmatch[i].rm_so, match_len);
   799 #if ENABLE_VERSIONED_ATTRS   801 pe_unpack_versioned_parameters(xmlNode *versioned_params, 
const char *ra_version)
   803     GHashTable *hash = crm_str_table_new();
   805     if (versioned_params && ra_version) {
   806         GHashTable *node_hash = crm_str_table_new();
   807         xmlNode *attr_set = pcmk__xe_first_child(versioned_params);
   813                               crm_element_name(attr_set), node_hash, hash, NULL,
   817         g_hash_table_destroy(node_hash);
   828     gboolean ruleset_default = TRUE;
   833         ruleset_default = FALSE;
   845     return ruleset_default;
   851     xmlNode *expr = NULL;
   852     gboolean test = TRUE;
   853     gboolean empty = TRUE;
   854     gboolean passed = TRUE;
   855     gboolean do_and = TRUE;
   856     const char *value = NULL;
   866     for (expr = pcmk__xe_first_child(rule); expr != NULL;
   867          expr = pcmk__xe_next(expr)) {
   872         if (test && do_and == FALSE) {
   876         } 
else if (test == FALSE && do_and) {
   883         crm_err(
"Invalid Rule %s: rules must contain at least one expression", 
ID(rule));
   886     crm_trace(
"Rule %s %s", 
ID(rule), passed ? 
"passed" : 
"failed");
   893     gboolean accept = FALSE;
   894     const char *
uname = NULL;
   926 #if ENABLE_VERSIONED_ATTRS   929                 g_hash_table_lookup_extended(rule_data->
node_hash,
   948               ID(expr), accept ? 
"passed" : 
"failed", 
uname ? 
uname : 
"all nodes");
   968 compare_attr_expr_vals(
const char *l_val, 
const char *r_val, 
const char *
type,
   973     if (l_val != NULL && r_val != NULL) {
   985             crm_trace(
"Defaulting to %s based comparison for '%s' op", 
type, op);
   989             cmp = strcasecmp(l_val, r_val);
   998             if (rc1 == 0 && rc2 == 0) {
   999                 if (l_val_num < r_val_num) {
  1001                 } 
else if (l_val_num > r_val_num) {
  1008                 crm_debug(
"Integer parse error. Comparing %s and %s as strings",
  1010                 cmp = compare_attr_expr_vals(l_val, r_val, 
"string", op);
  1021                 if (l_val_num < r_val_num) {
  1023                 } 
else if (l_val_num > r_val_num) {
  1030                 crm_debug(
"Floating-point parse error. Comparing %s and %s as "  1031                           "strings", l_val, r_val);
  1032                 cmp = compare_attr_expr_vals(l_val, r_val, 
"string", op);
  1040     } 
else if (l_val == NULL && r_val == NULL) {
  1042     } 
else if (r_val == NULL) {
  1066 accept_attr_expr(
const char *l_val, 
const char *r_val, 
const char *
type,
  1072         return (l_val != NULL);
  1075         return (l_val == NULL);
  1079     cmp = compare_attr_expr_vals(l_val, r_val, 
type, op);
  1087     } 
else if (l_val == NULL || r_val == NULL) {
  1110     gboolean attr_allocated = FALSE;
  1111     const char *h_val = NULL;
  1112     GHashTable *table = NULL;
  1114     const char *op = NULL;
  1115     const char *
type = NULL;
  1116     const char *attr = NULL;
  1117     const char *value = NULL;
  1118     const char *value_source = NULL;
  1126     if (attr == NULL || op == NULL) {
  1127         pe_err(
"Invalid attribute or operation in expression"  1136             if (resolved_attr) {
  1137                 attr = (
const char *) resolved_attr;
  1138                 attr_allocated = TRUE;
  1150         const char *param_name = value;
  1151         const char *param_value = NULL;
  1153         if (param_name && param_name[0]) {
  1154             if ((param_value = (
const char *)g_hash_table_lookup(table, param_name))) {
  1155                 value = param_value;
  1161         h_val = (
const char *)g_hash_table_lookup(rule_data->
node_hash, attr);
  1164     if (attr_allocated) {
  1169     return accept_attr_expr(h_val, value, 
type, op);
  1179     const char *value = NULL;
  1182     xmlNode *duration_spec = NULL;
  1183     xmlNode *date_spec = NULL;
  1194     if (value != NULL) {
  1198     if (value != NULL) {
  1202     if (start != NULL && end == NULL && duration_spec != NULL) {
  1207         if ((start == NULL) && (end == NULL)) {
  1211             crm_time_set_if_earlier(next_change, start);
  1216             if (end && next_change) {
  1219                 crm_time_set_if_earlier(next_change, end);
  1228         if (start == NULL) {
  1237             crm_time_set_if_earlier(next_change, start);
  1245             crm_time_set_if_earlier(next_change, end);
  1262     crm_trace(
"Testing op_defaults expression: %s", 
ID(expr));
  1264     if (rule_data->
op_data == NULL) {
  1265         crm_trace(
"No operations data provided");
  1270     if (interval == 0 && errno != 0) {
  1271         crm_trace(
"Could not parse interval: %s", interval_s);
  1291     gboolean accept = FALSE;
  1292     const char *op = NULL;
  1293     const char *value = NULL;
  1336     crm_trace(
"Testing rsc_defaults expression: %s", 
ID(expr));
  1343     if (
class != NULL &&
  1384                                 const char *set_name, GHashTable *node_hash,
  1385                                 GHashTable *hash, 
const char *always_first,
  1397     return pe_test_rule(rule, node_hash, role, now, NULL, NULL);
  1404                                     .
re = re_match_data,
  1408     return pe_test_rule(rule, node_hash, role, now, NULL, &match_data);
  1415     return pe_test_rule(rule, node_hash, role, now, NULL, match_data);
  1428                                     .
re = re_match_data,
  1445                            GHashTable *node_hash, GHashTable *hash,
  1446                            const char *always_first, gboolean overwrite,
  1458     unpack_nvpair_blocks(top, xml_obj, set_name, hash, always_first,
  1459                          overwrite, &rule_data, NULL, unpack_attr_set);
 #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)
 
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 pe_eval_date_expression(xmlNode *expr, crm_time_t *now, crm_time_t *next_change)
 
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)
 
guint crm_parse_interval_spec(const char *input)
Parse milliseconds from a Pacemaker interval specification.
 
#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)
 
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.
 
gboolean pe_test_attr_expression(xmlNode *expr, GHashTable *hash, crm_time_t *now, pe_match_data_t *match_data)
 
#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)
 
long long crm_parse_ll(const char *text, const char *default_text)
Parse a long long integer value from a string.
 
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)
 
gboolean pe_test_role_expression(xmlNode *expr, enum rsc_role_e role, crm_time_t *now)
 
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)
 
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)
 
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)
 
gboolean pe_test_date_expression(xmlNode *expr, crm_time_t *now, crm_time_t *next_change)
 
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 update_field(xml_field, time_fn)
 
enum crm_ais_msg_types type
 
#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)