pacemaker  2.1.9-49aab99839
Scalable High-Availability cluster resource manager
scores.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2024 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU Lesser General Public License
7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 
12 #ifndef _GNU_SOURCE
13 # define _GNU_SOURCE
14 #endif
15 
16 #include <stdio.h> // snprintf(), NULL
17 #include <string.h> // strcpy(), strdup()
18 #include <ctype.h> // isspace()
19 #include <sys/types.h> // size_t
20 
24 
38 int
39 pcmk_parse_score(const char *score_s, int *score, int default_score)
40 {
41  int rc = pcmk_rc_ok;
42  int local_score = 0;
43 
44  // Ensure default score is in bounds
45  default_score = QB_MIN(default_score, PCMK_SCORE_INFINITY);
46  default_score = QB_MAX(default_score, -PCMK_SCORE_INFINITY);
47  local_score = default_score;
48 
49  if (score_s == NULL) {
50 
51  } else if (pcmk_str_is_minus_infinity(score_s)) {
52  local_score = -PCMK_SCORE_INFINITY;
53 
54  } else if (pcmk_str_is_infinity(score_s)) {
55  local_score = PCMK_SCORE_INFINITY;
56 
57  } else if (pcmk__str_eq(score_s, PCMK_VALUE_RED, pcmk__str_casei)) {
58  local_score = pcmk__score_red;
59 
60  } else if (pcmk__str_eq(score_s, PCMK_VALUE_YELLOW, pcmk__str_casei)) {
61  local_score = pcmk__score_yellow;
62 
63  } else if (pcmk__str_eq(score_s, PCMK_VALUE_GREEN, pcmk__str_casei)) {
64  local_score = pcmk__score_green;
65 
66  } else {
67  long long score_ll = 0LL;
68 
69  rc = pcmk__scan_ll(score_s, &score_ll, default_score);
70  if ((rc == EOVERFLOW) || (rc == ERANGE)) {
71  const char *c = score_s;
72 
73  while (isspace(*c)) {
74  ++c;
75  }
76  rc = pcmk_rc_ok;
77  if (*c == '-') {
78  score_ll = -PCMK_SCORE_INFINITY;
79  } else {
80  score_ll = PCMK_SCORE_INFINITY;
81  }
82  }
83  if (rc != pcmk_rc_ok) {
84  local_score = default_score;
85 
86  } else if (score_ll > PCMK_SCORE_INFINITY) {
87  local_score = PCMK_SCORE_INFINITY;
88 
89  } else if (score_ll < -PCMK_SCORE_INFINITY) {
90  local_score = -PCMK_SCORE_INFINITY;
91 
92  } else {
93  local_score = (int) score_ll;
94  }
95  }
96 
97  if (score != NULL) {
98  *score = local_score;
99  }
100  return rc;
101 }
102 
114 int
115 char2score(const char *score)
116 {
117  int result = 0;
118 
119  (void) pcmk_parse_score(score, &result, 0);
120  return result;
121 }
122 
136 const char *
138 {
139  // The longest possible result is "-INFINITY"
140  static char score_s[sizeof(PCMK_VALUE_MINUS_INFINITY)];
141 
142  if (score >= PCMK_SCORE_INFINITY) {
143  strcpy(score_s, PCMK_VALUE_INFINITY);
144 
145  } else if (score <= -PCMK_SCORE_INFINITY) {
146  strcpy(score_s, PCMK_VALUE_MINUS_INFINITY);
147 
148  } else {
149  // Range is limited to +/-1000000, so no chance of overflow
150  snprintf(score_s, sizeof(score_s), "%d", score);
151  }
152 
153  return score_s;
154 }
155 
166 int
167 pcmk__add_scores(int score1, int score2)
168 {
169  /* As long as PCMK_SCORE_INFINITY is less than half of the maximum integer,
170  * we can ignore the possibility of integer overflow.
171  */
172  int result = score1 + score2;
173 
174  // First handle the cases where one or both is infinite
175  if ((score1 <= -PCMK_SCORE_INFINITY) || (score2 <= -PCMK_SCORE_INFINITY)) {
176  return -PCMK_SCORE_INFINITY;
177  }
178  if ((score1 >= PCMK_SCORE_INFINITY) || (score2 >= PCMK_SCORE_INFINITY)) {
179  return PCMK_SCORE_INFINITY;
180  }
181 
182  // Bound result to infinity.
183  if (result >= PCMK_SCORE_INFINITY) {
184  return PCMK_SCORE_INFINITY;
185  }
186  if (result <= -PCMK_SCORE_INFINITY) {
187  return -PCMK_SCORE_INFINITY;
188  }
189 
190  return result;
191 }
192 
193 // Deprecated functions kept only for backward API compatibility
194 // LCOV_EXCL_START
195 
197 
198 char *
199 score2char(int score)
200 {
201  return pcmk__str_copy(pcmk_readable_score(score));
202 }
203 
204 char *
205 score2char_stack(int score, char *buf, size_t len)
206 {
207  CRM_CHECK((buf != NULL) && (len >= sizeof(PCMK_VALUE_MINUS_INFINITY)),
208  return NULL);
209  strcpy(buf, pcmk_readable_score(score));
210  return buf;
211 }
212 
213 // LCOV_EXCL_STOP
214 // End deprecated API
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:245
#define PCMK_VALUE_GREEN
Definition: options.h:157
#define PCMK_VALUE_MINUS_INFINITY
Definition: options.h:173
#define PCMK_VALUE_INFINITY
Definition: options.h:163
int pcmk__add_scores(int score1, int score2)
Definition: scores.c:167
int pcmk__score_yellow
Definition: scores.c:23
int char2score(const char *score)
Get the integer value of a score string.
Definition: scores.c:115
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
Definition: strings.c:96
#define PCMK_VALUE_RED
Definition: options.h:197
int pcmk_parse_score(const char *score_s, int *score, int default_score)
Parse an integer score from a string.
Definition: scores.c:39
int pcmk__score_red
Definition: scores.c:21
int pcmk__score_green
Definition: scores.c:22
const char * pcmk_readable_score(int score)
Return a displayable static string for a score value.
Definition: scores.c:137
char * score2char(int score)
Definition: scores.c:199
bool pcmk_str_is_infinity(const char *s)
Definition: utils.c:340
#define pcmk__str_copy(str)
pcmk__action_result_t result
Definition: pcmk_fence.c:35
bool pcmk_str_is_minus_infinity(const char *s)
Definition: utils.c:346
Deprecated Pacemaker score APIs.
#define PCMK_VALUE_YELLOW
Definition: options.h:221
char * score2char_stack(int score, char *buf, size_t len)
Definition: scores.c:205
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition: scores.h:24