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);
   158     uint32_t epact, diy, goldn;
   163     goldn = (y % 19) + 1;
   164     epact = (11 * goldn + 18) % 30;
   165     if ((epact == 25 && goldn > 11) || epact == 24)
   168     return ((((((diy + epact) * 6) + 11) % 177) / 22) & 7);
   172 check_one(xmlNode *cron_spec, 
const char *xml_field, uint32_t time_field) {
   184     } 
else if (low == high) {
   186         if (time_field < low) {
   188         } 
else if (time_field > high) {
   193     } 
else if (low != -1 && high != -1) {
   195         if (time_field < low) {
   197         } 
else if (time_field > high) {
   202     } 
else if (low == -1) {
   205     } 
else if (high == -1) {
   212         crm_debug(
"Condition '%s' in %s: passed", value, xml_field);
   214         crm_debug(
"Condition '%s' in %s: failed", value, xml_field);
   221 check_passes(
int rc) {
   230 #define CHECK_ONE(spec, name, var) do { \   231     int subpart_rc = check_one(spec, name, var); \   232     if (check_passes(subpart_rc) == FALSE) { \   240     uint32_t h, m, s, y, d, w;
   262     CHECK_ONE(cron_spec, 
"moon", phase_of_the_moon(now));
   272 update_field(
crm_time_t *t, xmlNode *xml, 
const char *attr,
   278         && (value != 0LL) && (value >= INT_MIN) && (value <= INT_MAX)) {
   279         time_fn(t, (
int) value);
   303     if ((next_change != NULL) && (t != NULL)) {
   312 typedef struct sorted_set_s {
   315     const char *special_name;   
   320 sort_pairs(gconstpointer a, gconstpointer b)
   325     if (a == NULL && b == NULL) {
   327     } 
else if (a == NULL) {
   329     } 
else if (b == NULL) {
   333     if (pcmk__str_eq(pair_a->name, pair_a->special_name, 
pcmk__str_casei)) {
   336     } 
else if (pcmk__str_eq(pair_b->name, pair_a->special_name, 
pcmk__str_casei)) {
   340     if (pair_a->score < pair_b->score) {
   342     } 
else if (pair_a->score > pair_b->score) {
   349 populate_hash(xmlNode * nvpair_list, GHashTable * hash, gboolean overwrite, xmlNode * top)
   351     const char *
name = NULL;
   352     const char *value = NULL;
   353     const char *old_value = NULL;
   354     xmlNode *list = nvpair_list;
   355     xmlNode *an_attr = NULL;
   357     name = crm_element_name(list->children);
   359         list = list->children;
   362     for (an_attr = pcmk__xe_first_child(list); an_attr != NULL;
   363          an_attr = pcmk__xe_next(an_attr)) {
   378             if (
name == NULL || value == NULL) {
   382             old_value = g_hash_table_lookup(hash, 
name);
   386                     crm_trace(
"Letting %s default (removing explicit value \"%s\")",
   388                     g_hash_table_remove(hash, 
name);
   392             } 
else if (old_value == NULL) {
   394                 g_hash_table_insert(hash, strdup(
name), strdup(value));
   396             } 
else if (overwrite) {
   397                 crm_trace(
"Setting %s=\"%s\" (overwriting old value \"%s\")",
   398                           name, value, old_value);
   399                 g_hash_table_replace(hash, strdup(
name), strdup(value));
   405 typedef struct unpack_data_s {
   414 unpack_attr_set(gpointer 
data, gpointer user_data)
   420                        unpack_data->next_change)) {
   424     crm_trace(
"Adding attributes from %s (score %d) %s overwrite",
   425               pair->name, pair->score,
   426               (unpack_data->overwrite? 
"with" : 
"without"));
   427     populate_hash(pair->attr_set, unpack_data->hash, unpack_data->overwrite, unpack_data->top);
   442 make_pairs(xmlNode *top, 
const xmlNode *xml_obj, 
const char *set_name,
   443            const char *always_first)
   445     GList *unsorted = NULL;
   447     if (xml_obj == NULL) {
   450     for (xmlNode *attr_set = pcmk__xe_first_child(xml_obj); attr_set != NULL;
   451          attr_set = pcmk__xe_next(attr_set)) {
   453         if (pcmk__str_eq(set_name, (
const char *) attr_set->name,
   455             const char *score = NULL;
   457             xmlNode *expanded_attr_set = 
expand_idref(attr_set, top);
   459             if (expanded_attr_set == NULL) {
   465             pair->name = 
ID(expanded_attr_set);
   466             pair->special_name = always_first;
   467             pair->attr_set = expanded_attr_set;
   472             unsorted = g_list_prepend(unsorted, pair);
   475     return g_list_sort(unsorted, sort_pairs);
   493 unpack_nvpair_blocks(xmlNode *top, 
const xmlNode *xml_obj, 
const char *set_name,
   494                      void *hash, 
const char *always_first, gboolean overwrite,
   498     GList *pairs = make_pairs(top, xml_obj, set_name, always_first);
   503             .overwrite = overwrite,
   504             .next_change = next_change,
   506             .rule_data = rule_data
   509         g_list_foreach(pairs, unpack_func, &
data);
   510         g_list_free_full(pairs, free);
   517                 const char *always_first, gboolean overwrite,
   520     unpack_nvpair_blocks(top, xml_obj, set_name, hash, always_first,
   521                          overwrite, rule_data, next_change, unpack_attr_set);
   539                   GHashTable *node_hash, GHashTable *hash,
   540                   const char *always_first, gboolean overwrite,
   553                     always_first, overwrite, next_change);
   561     const char *p, *last_match_index;
   562     char *p_dst, *
result = NULL;
   564     if (pcmk__str_empty(
string) || !match_data) {
   568     p = last_match_index = string;
   571         if (*p == 
'%' && *(p + 1) && isdigit(*(p + 1))) {
   573             if (match_data->
nregs >= i && match_data->
pmatch[i].rm_so != -1 &&
   574                 match_data->
pmatch[i].rm_eo > match_data->
pmatch[i].rm_so) {
   575                 len += p - last_match_index + (match_data->
pmatch[i].rm_eo - match_data->
pmatch[i].rm_so);
   576                 last_match_index = p + 2;
   582     len += p - last_match_index + 1;
   589     p_dst = 
result = calloc(1, len);
   593         if (*p == 
'%' && *(p + 1) && isdigit(*(p + 1))) {
   595             if (match_data->
nregs >= i && match_data->
pmatch[i].rm_so != -1 &&
   596                 match_data->
pmatch[i].rm_eo > match_data->
pmatch[i].rm_so) {
   598                 int match_len = match_data->
pmatch[i].rm_eo - match_data->
pmatch[i].rm_so;
   599                 memcpy(p_dst, match_data->
string + match_data->
pmatch[i].rm_so, match_len);
   617     gboolean ruleset_default = TRUE;
   622         ruleset_default = FALSE;
   634     return ruleset_default;
   640     xmlNode *expr = NULL;
   641     gboolean test = TRUE;
   642     gboolean empty = TRUE;
   643     gboolean passed = TRUE;
   644     gboolean do_and = TRUE;
   645     const char *value = NULL;
   655     for (expr = pcmk__xe_first_child(rule); expr != NULL;
   656          expr = pcmk__xe_next(expr)) {
   661         if (test && do_and == FALSE) {
   665         } 
else if (test == FALSE && do_and) {
   672         crm_err(
"Invalid Rule %s: rules must contain at least one expression", 
ID(rule));
   675     crm_trace(
"Rule %s %s", 
ID(rule), passed ? 
"passed" : 
"failed");
   682     gboolean accept = FALSE;
   683     const char *
uname = NULL;
   733               ID(expr), accept ? 
"passed" : 
"failed", 
uname ? 
uname : 
"all nodes");
   753 compare_attr_expr_vals(
const char *l_val, 
const char *r_val, 
const char *
type,
   758     if (l_val != NULL && r_val != NULL) {
   770             crm_trace(
"Defaulting to %s based comparison for '%s' op", 
type, op);
   774             cmp = strcasecmp(l_val, r_val);
   784                 if (l_val_num < r_val_num) {
   786                 } 
else if (l_val_num > r_val_num) {
   793                 crm_debug(
"Integer parse error. Comparing %s and %s as strings",
   795                 cmp = compare_attr_expr_vals(l_val, r_val, 
"string", op);
   806                 if (l_val_num < r_val_num) {
   808                 } 
else if (l_val_num > r_val_num) {
   815                 crm_debug(
"Floating-point parse error. Comparing %s and %s as "   816                           "strings", l_val, r_val);
   817                 cmp = compare_attr_expr_vals(l_val, r_val, 
"string", op);
   825     } 
else if (l_val == NULL && r_val == NULL) {
   827     } 
else if (r_val == NULL) {
   851 accept_attr_expr(
const char *l_val, 
const char *r_val, 
const char *
type,
   857         return (l_val != NULL);
   860         return (l_val == NULL);
   864     cmp = compare_attr_expr_vals(l_val, r_val, 
type, op);
   872     } 
else if (l_val == NULL || r_val == NULL) {
   901 expand_value_source(
const char *value, 
const char *value_source,
   904     GHashTable *table = NULL;
   906     if (pcmk__str_empty(value)) {
   910         table = match_data->
params;
   913         table = match_data->
meta;
   922     return (
const char *) g_hash_table_lookup(table, value);
   938     gboolean attr_allocated = FALSE;
   939     const char *h_val = NULL;
   941     const char *op = NULL;
   942     const char *
type = NULL;
   943     const char *attr = NULL;
   944     const char *value = NULL;
   945     const char *value_source = NULL;
   955                " not specified", pcmk__s(
ID(expr), 
"without ID"));
   957     } 
else if (op == NULL) {
   959                " not specified", pcmk__s(
ID(expr), 
"without ID"));
   967             if (resolved_attr != NULL) {
   968                 attr = (
const char *) resolved_attr;
   969                 attr_allocated = TRUE;
   974         value = expand_value_source(value, value_source, rule_data->
match_data);
   978         h_val = (
const char *)g_hash_table_lookup(rule_data->
node_hash, attr);
   981     if (attr_allocated) {
   986     return accept_attr_expr(h_val, value, 
type, op);
  1004     const char *value = NULL;
  1007     xmlNode *duration_spec = NULL;
  1008     xmlNode *date_spec = NULL;
  1019     if (value != NULL) {
  1023     if (value != NULL) {
  1027     if (start != NULL && end == NULL && duration_spec != NULL) {
  1032         if ((start == NULL) && (end == NULL)) {
  1036             crm_time_set_if_earlier(next_change, start);
  1041             if (end && next_change) {
  1044                 crm_time_set_if_earlier(next_change, end);
  1053         if (start == NULL) {
  1062             crm_time_set_if_earlier(next_change, start);
  1070             crm_time_set_if_earlier(next_change, end);
  1087     crm_trace(
"Testing op_defaults expression: %s", 
ID(expr));
  1089     if (rule_data->
op_data == NULL) {
  1090         crm_trace(
"No operations data provided");
  1095     if (interval == 0 && errno != 0) {
  1096         crm_trace(
"Could not parse interval: %s", interval_s);
  1125     gboolean accept = FALSE;
  1126     const char *op = NULL;
  1127     const char *value = NULL;
  1172     crm_trace(
"Testing rsc_defaults expression: %s", 
ID(expr));
  1179     if (
class != NULL &&
  1215     return pe_test_rule(rule, node_hash, role, now, NULL, NULL);
  1222                                     .
re = re_match_data,
  1226     return pe_test_rule(rule, node_hash, role, now, NULL, &match_data);
  1233     return pe_test_rule(rule, node_hash, role, now, NULL, match_data);
  1246                                     .
re = re_match_data,
  1263                            GHashTable *node_hash, GHashTable *hash,
  1264                            const char *always_first, gboolean overwrite,
  1276     unpack_nvpair_blocks(top, xml_obj, set_name, hash, always_first,
  1277                          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)
 
int crm_time_get_isoweek(const crm_time_t *dt, uint32_t *y, uint32_t *w, uint32_t *d)
 
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)
 
void pe_eval_nvpairs(xmlNode *top, const 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)
 
int char2score(const char *score)
Get the integer value of a score string. 
 
crm_time_t * pcmk_copy_time(const crm_time_t *source)
 
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. 
 
#define XML_NVPAIR_ATTR_NAME
 
#define CHECK_ONE(spec, name, var)
 
enum crm_ais_msg_types type
 
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
 
int crm_time_get_ordinal(const crm_time_t *dt, uint32_t *y, uint32_t *d)
 
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)
 
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...)
 
void crm_time_set(crm_time_t *target, const crm_time_t *source)
 
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. 
 
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)
 
int crm_time_get_gregorian(const crm_time_t *dt, uint32_t *y, uint32_t *m, uint32_t *d)
 
enum rsc_role_e text2role(const char *role)
 
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
 
int pcmk__scan_double(const char *text, double *result, const char *default_text, char **end_text)
 
pe_rsc_eval_data_t * rsc_data
 
int crm_time_compare(const crm_time_t *a, const crm_time_t *b)
 
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
 
pcmk__action_result_t result
 
#define PCMK_XE_DATE_EXPRESSION
 
#define crm_err(fmt, args...)
 
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)
 
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)
 
rsc_role_e
Possible roles that a resource can be in. 
 
int pcmk__parse_ll_range(const char *srcstring, long long *start, long long *end)
 
#define PCMK_XE_OP_EXPRESSION
 
#define XML_TAG_EXPRESSION
 
#define PCMK_XE_RSC_EXPRESSION
 
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_timeofday(const crm_time_t *dt, uint32_t *h, uint32_t *m, uint32_t *s)
 
#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)