1 #include "src/config.h"
2 #include <stdio.h>
3 #include <platform/cbassert.h>
4 #include <ctype.h>
5 #include <errno.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <math.h>
9 #include <stdarg.h>
10 
11 #include "memcached.h"
12 
safe_strtoull(const char *str, uint64_t *out)13 bool safe_strtoull(const char *str, uint64_t *out) {
14     char *endptr;
15     unsigned long long ull;
16 
17     cb_assert(out != NULL);
18     errno = 0;
19     *out = 0;
20     ull = strtoull(str, &endptr, 10);
21     if (errno == ERANGE)
22         return false;
23     if (isspace(*endptr) || (*endptr == '\0' && endptr != str)) {
24         if ((long long) ull < 0) {
25             /* only check for negative signs in the uncommon case when
26              * the unsigned number is so big that it's negative as a
27              * signed number. */
28             if (strchr(str, '-') != NULL) {
29                 return false;
30             }
31         }
32         *out = ull;
33         return true;
34     }
35     return false;
36 }
37 
safe_strtoll(const char *str, int64_t *out)38 bool safe_strtoll(const char *str, int64_t *out) {
39     char *endptr;
40     long long ll;
41 
42     cb_assert(out != NULL);
43     errno = 0;
44     *out = 0;
45     ll = strtoll(str, &endptr, 10);
46     if (errno == ERANGE)
47         return false;
48     if (isspace(*endptr) || (*endptr == '\0' && endptr != str)) {
49         *out = ll;
50         return true;
51     }
52     return false;
53 }
54 
safe_strtoul(const char *str, uint32_t *out)55 bool safe_strtoul(const char *str, uint32_t *out) {
56     char *endptr = NULL;
57     unsigned long l = 0;
58     cb_assert(out);
59     cb_assert(str);
60     *out = 0;
61     errno = 0;
62 
63     l = strtoul(str, &endptr, 10);
64     if (errno == ERANGE) {
65         return false;
66     }
67 
68     if (isspace(*endptr) || (*endptr == '\0' && endptr != str)) {
69         if ((long) l < 0) {
70             /* only check for negative signs in the uncommon case when
71              * the unsigned number is so big that it's negative as a
72              * signed number. */
73             if (strchr(str, '-') != NULL) {
74                 return false;
75             }
76         }
77         *out = l;
78         return true;
79     }
80 
81     return false;
82 }
83 
safe_strtol(const char *str, int32_t *out)84 bool safe_strtol(const char *str, int32_t *out) {
85     char *endptr;
86     long l;
87     cb_assert(out != NULL);
88     errno = 0;
89     *out = 0;
90     l = strtol(str, &endptr, 10);
91     if (errno == ERANGE)
92         return false;
93     if (isspace(*endptr) || (*endptr == '\0' && endptr != str)) {
94         *out = l;
95         return true;
96     }
97     return false;
98 }
99 
timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)100 int timeval_subtract(struct timeval *result,
101                             struct timeval *x, struct timeval *y)
102 {
103     /* Perform the carry for the later subtraction by updating y. */
104     if (x->tv_usec < y->tv_usec) {
105         int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
106         y->tv_usec -= 1000000 * nsec;
107         y->tv_sec += nsec;
108     }
109     if (x->tv_usec - y->tv_usec > 1000000) {
110         int nsec = (x->tv_usec - y->tv_usec) / 1000000;
111         y->tv_usec += 1000000 * nsec;
112         y->tv_sec -= nsec;
113     }
114 
115     /* Compute the time remaining to wait.
116        tv_usec is certainly positive. */
117     result->tv_sec = x->tv_sec - y->tv_sec;
118     result->tv_usec = x->tv_usec - y->tv_usec;
119 
120     /* Return 1 if result is negative. */
121     return x->tv_sec < y->tv_sec;
122 }
123 
timeval_to_double(struct timeval tv)124 double timeval_to_double(struct timeval tv)
125 {
126     return (double)tv.tv_sec + ((double)tv.tv_usec / 1000000);
127 }
128 
cmp_doubles(const void *pa, const void *pb)129 static int cmp_doubles(const void *pa, const void *pb)
130 {
131     double a = *(double*)pa;
132     double b = *(double*)pb;
133     return a == b ? 0 : (a < b ? -1 : 1);
134 }
135 
compute_stats(struct moxi_stats *out, double *vals, int num_vals)136 void compute_stats(struct moxi_stats *out, double *vals, int num_vals)
137 {
138     double sum = 0;
139     int i;
140 
141     cb_assert(out);
142     cb_assert(vals);
143     cb_assert(num_vals > 0);
144 
145     out->min = vals[0];
146     out->max = vals[0];
147 
148     /* min, max and sum */
149     for (i = 0; i < num_vals; i++) {
150         sum += vals[i];
151         out->min = fmin(out->min, vals[i]);
152         out->max = fmax(out->max, vals[i]);
153     }
154 
155     /* avg */
156     out->avg = sum / (double)num_vals;
157 
158     /* stddev */
159     sum = 0;
160     for (i = 0; i < num_vals; i++) {
161         sum += pow(vals[i] - out->avg, 2);
162     }
163 
164     out->stddev = sqrt(sum / num_vals);
165 
166     /* 95th %ile */
167     qsort(vals, num_vals, sizeof(double), cmp_doubles);
168     out->ninetyfifth = vals[(int)((float)num_vals * 0.95)];
169 }
170 
vperror(const char *fmt, ...)171 void vperror(const char *fmt, ...) {
172     int old_errno = errno;
173     char buf[80];
174     va_list ap;
175 
176     va_start(ap, fmt);
177     vsnprintf(buf, sizeof(buf), fmt, ap);
178     va_end(ap);
179 
180     errno = old_errno;
181 
182     perror(buf);
183 }
184