summaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
authordormando <dormando@rydia.net>2017-06-27 12:17:59 -0700
committerdormando <dormando@rydia.net>2019-09-17 02:37:15 -0700
commitb5ea90160579ba060b8e1d269595b3ec5d77d740 (patch)
tree96d5dc43912f32b4d48d6a19cf161052e9aaa137 /util.c
parent554b56687a19300a75ec24184746b5512580c819 (diff)
downloadmemcached-b5ea90160579ba060b8e1d269595b3ec5d77d740.tar.gz
restartable cache
"-e /path/to/tmpfsmnt/file" SIGUSR1 for graceful stop restart requires the same memory limit, slab sizes, and some other infrequently changed details. Most other options and features can change between restarts. Binary can be upgraded between restarts. Restart does some fixup work on start for every item in cache. Can take over a minute with more than a few hundred million items in cache. Keep in mind when a cache is down it may be missing invalidations, updates, and so on.
Diffstat (limited to 'util.c')
-rw-r--r--util.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/util.c b/util.c
index 13e86ac..adf0f1d 100644
--- a/util.c
+++ b/util.c
@@ -71,6 +71,36 @@ bool safe_strtoull(const char *str, uint64_t *out) {
return false;
}
+/* Could macro this. Decided to keep this unrolled for safety rather than add
+ * the base parameter to all callers. Very few places need to parse a number
+ * outside of base 10, currently exactly once, so splitting this up should
+ * help avoid typo bugs.
+ */
+bool safe_strtoull_hex(const char *str, uint64_t *out) {
+ assert(out != NULL);
+ errno = 0;
+ *out = 0;
+ char *endptr;
+ unsigned long long ull = strtoull(str, &endptr, 16);
+ if ((errno == ERANGE) || (str == endptr)) {
+ return false;
+ }
+
+ if (xisspace(*endptr) || (*endptr == '\0' && endptr != str)) {
+ if ((long long) ull < 0) {
+ /* only check for negative signs in the uncommon case when
+ * the unsigned number is so big that it's negative as a
+ * signed number. */
+ if (strchr(str, '-') != NULL) {
+ return false;
+ }
+ }
+ *out = ull;
+ return true;
+ }
+ return false;
+}
+
bool safe_strtoll(const char *str, int64_t *out) {
assert(out != NULL);
errno = 0;
@@ -151,6 +181,28 @@ bool safe_strtod(const char *str, double *out) {
return false;
}
+// slow, safe function for copying null terminated buffers.
+// ensures null terminator set on destination buffer. copies at most dstmax-1
+// non-null bytes.
+// Explicitly avoids over-reading src while looking for the null byte.
+// returns true if src was fully copied.
+// returns false if src was truncated into dst.
+bool safe_strcpy(char *dst, const char *src, const size_t dstmax) {
+ size_t x;
+
+ for (x = 0; x < dstmax - 1 && src[x] != '\0'; x++) {
+ dst[x] = src[x];
+ }
+
+ dst[x] = '\0';
+
+ if (src[x] == '\0') {
+ return true;
+ } else {
+ return false;
+ }
+}
+
void vperror(const char *fmt, ...) {
int old_errno = errno;
char buf[1024];