pacemaker  2.1.3-ea053b43a
Scalable High-Availability cluster resource manager
scores.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2022 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 <sys/types.h> // size_t
19 
23 
35 int
36 char2score(const char *score)
37 {
38  if (score == NULL) {
39  return 0;
40 
41  } else if (pcmk_str_is_minus_infinity(score)) {
42  return -CRM_SCORE_INFINITY;
43 
44  } else if (pcmk_str_is_infinity(score)) {
45  return CRM_SCORE_INFINITY;
46 
47  } else if (pcmk__str_eq(score, PCMK__VALUE_RED, pcmk__str_casei)) {
48  return pcmk__score_red;
49 
50  } else if (pcmk__str_eq(score, PCMK__VALUE_YELLOW, pcmk__str_casei)) {
51  return pcmk__score_yellow;
52 
53  } else if (pcmk__str_eq(score, PCMK__VALUE_GREEN, pcmk__str_casei)) {
54  return pcmk__score_green;
55 
56  } else {
57  long long score_ll;
58 
59  pcmk__scan_ll(score, &score_ll, 0LL);
60  if (score_ll > CRM_SCORE_INFINITY) {
61  return CRM_SCORE_INFINITY;
62 
63  } else if (score_ll < -CRM_SCORE_INFINITY) {
64  return -CRM_SCORE_INFINITY;
65 
66  } else {
67  return (int) score_ll;
68  }
69  }
70 }
71 
84 char *
85 score2char_stack(int score, char *buf, size_t len)
86 {
87  CRM_CHECK((buf != NULL) && (len >= sizeof(CRM_MINUS_INFINITY_S)),
88  return NULL);
89 
90  if (score >= CRM_SCORE_INFINITY) {
91  strcpy(buf, CRM_INFINITY_S);
92  } else if (score <= -CRM_SCORE_INFINITY) {
93  strcpy(buf, CRM_MINUS_INFINITY_S);
94  } else {
95  snprintf(buf, len, "%d", score);
96  }
97  return buf;
98 }
99 
113 char *
114 score2char(int score)
115 {
116  char *result = NULL;
117 
118  if (score >= CRM_SCORE_INFINITY) {
119  result = strdup(CRM_INFINITY_S);
120  CRM_ASSERT(result != NULL);
121 
122  } else if (score <= -CRM_SCORE_INFINITY) {
123  result = strdup(CRM_MINUS_INFINITY_S);
124  CRM_ASSERT(result != NULL);
125 
126  } else {
127  result = pcmk__itoa(score);
128  }
129  return result;
130 }
131 
139 int
140 pcmk__add_scores(int score1, int score2)
141 {
142  int result = score1 + score2;
143 
144  // First handle the cases where one or both is infinite
145 
146  if (score1 <= -CRM_SCORE_INFINITY) {
147 
148  if (score2 <= -CRM_SCORE_INFINITY) {
149  crm_trace("-INFINITY + -INFINITY = -INFINITY");
150  } else if (score2 >= CRM_SCORE_INFINITY) {
151  crm_trace("-INFINITY + +INFINITY = -INFINITY");
152  } else {
153  crm_trace("-INFINITY + %d = -INFINITY", score2);
154  }
155 
156  return -CRM_SCORE_INFINITY;
157 
158  } else if (score2 <= -CRM_SCORE_INFINITY) {
159 
160  if (score1 >= CRM_SCORE_INFINITY) {
161  crm_trace("+INFINITY + -INFINITY = -INFINITY");
162  } else {
163  crm_trace("%d + -INFINITY = -INFINITY", score1);
164  }
165 
166  return -CRM_SCORE_INFINITY;
167 
168  } else if (score1 >= CRM_SCORE_INFINITY) {
169 
170  if (score2 >= CRM_SCORE_INFINITY) {
171  crm_trace("+INFINITY + +INFINITY = +INFINITY");
172  } else {
173  crm_trace("+INFINITY + %d = +INFINITY", score2);
174  }
175 
176  return CRM_SCORE_INFINITY;
177 
178  } else if (score2 >= CRM_SCORE_INFINITY) {
179  crm_trace("%d + +INFINITY = +INFINITY", score1);
180  return CRM_SCORE_INFINITY;
181  }
182 
183  /* As long as CRM_SCORE_INFINITY is less than half of the maximum integer,
184  * we can ignore the possibility of integer overflow
185  */
186 
187  // Bound result to infinity
188 
189  if (result >= CRM_SCORE_INFINITY) {
190  crm_trace("%d + %d = +INFINITY", score1, score2);
191  return CRM_SCORE_INFINITY;
192 
193  } else if (result <= -CRM_SCORE_INFINITY) {
194  crm_trace("%d + %d = -INFINITY", score1, score2);
195  return -CRM_SCORE_INFINITY;
196  }
197 
198  crm_trace("%d + %d = %d", score1, score2, result);
199  return result;
200 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:226
#define PCMK__VALUE_GREEN
int pcmk__add_scores(int score1, int score2)
Definition: scores.c:140
int pcmk__score_yellow
Definition: scores.c:22
int char2score(const char *score)
Get the integer value of a score string.
Definition: scores.c:36
#define CRM_SCORE_INFINITY
Definition: crm.h:85
#define PCMK__VALUE_RED
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
Definition: strings.c:97
int pcmk__score_red
Definition: scores.c:20
#define crm_trace(fmt, args...)
Definition: logging.h:364
#define CRM_MINUS_INFINITY_S
Definition: crm.h:88
int pcmk__score_green
Definition: scores.c:21
char * score2char(int score)
Return the string equivalent of an integer score.
Definition: scores.c:114
bool pcmk_str_is_infinity(const char *s)
Definition: utils.c:513
pcmk__action_result_t result
Definition: pcmk_fence.c:34
#define CRM_ASSERT(expr)
Definition: results.h:42
bool pcmk_str_is_minus_infinity(const char *s)
Definition: utils.c:518
#define CRM_INFINITY_S
Definition: crm.h:86
#define PCMK__VALUE_YELLOW
char * score2char_stack(int score, char *buf, size_t len)
Convert an integer score to a string, using a provided buffer.
Definition: scores.c:85