-/* Check if the sds string 's' can be represented by a long long
- * (that is, is a number that fits into long without any other space or
- * character before or after the digits, so that converting this number
- * back to a string will result in the same bytes as the original string).
- *
- * If so, the function returns REDIS_OK and *llongval is set to the value
- * of the number. Otherwise REDIS_ERR is returned */
-int isStringRepresentableAsLongLong(sds s, long long *llongval) {
- char buf[32], *endptr;
- long long value;
- int slen;
-
- value = strtoll(s, &endptr, 10);
- if (endptr[0] != '\0') return REDIS_ERR;
- slen = ll2string(buf,32,value);
-
- /* If the number converted back into a string is not identical
- * then it's not possible to encode the string as integer */
- if (sdslen(s) != (unsigned)slen || memcmp(buf,s,slen)) return REDIS_ERR;
- if (llongval) *llongval = value;
- return REDIS_OK;
+/* Generate the Redis "Run ID", a SHA1-sized random number that identifies a
+ * given execution of Redis, so that if you are talking with an instance
+ * having run_id == A, and you reconnect and it has run_id == B, you can be
+ * sure that it is either a different instance or it was restarted. */
+void getRandomHexChars(char *p, unsigned int len) {
+ FILE *fp = fopen("/dev/urandom","r");
+ char *charset = "0123456789abcdef";
+ unsigned int j;
+
+ if (fp == NULL || fread(p,len,1,fp) == 0) {
+ /* If we can't read from /dev/urandom, do some reasonable effort
+ * in order to create some entropy, since this function is used to
+ * generate run_id and cluster instance IDs */
+ char *x = p;
+ unsigned int l = len;
+ struct timeval tv;
+ pid_t pid = getpid();
+
+ /* Use time and PID to fill the initial array. */
+ gettimeofday(&tv,NULL);
+ if (l >= sizeof(tv.tv_usec)) {
+ memcpy(x,&tv.tv_usec,sizeof(tv.tv_usec));
+ l -= sizeof(tv.tv_usec);
+ x += sizeof(tv.tv_usec);
+ }
+ if (l >= sizeof(tv.tv_sec)) {
+ memcpy(x,&tv.tv_sec,sizeof(tv.tv_sec));
+ l -= sizeof(tv.tv_sec);
+ x += sizeof(tv.tv_sec);
+ }
+ if (l >= sizeof(pid)) {
+ memcpy(x,&pid,sizeof(pid));
+ l -= sizeof(pid);
+ x += sizeof(pid);
+ }
+ /* Finally xor it with rand() output, that was already seeded with
+ * time() at startup. */
+ for (j = 0; j < len; j++)
+ p[j] ^= rand();
+ }
+ /* Turn it into hex digits taking just 4 bits out of 8 for every byte. */
+ for (j = 0; j < len; j++)
+ p[j] = charset[p[j] & 0x0F];
+ fclose(fp);
+}
+
+#ifdef UTIL_TEST_MAIN
+#include <assert.h>
+
+void test_string2ll(void) {
+ char buf[32];
+ long long v;
+
+ /* May not start with +. */
+ strcpy(buf,"+1");
+ assert(string2ll(buf,strlen(buf),&v) == 0);
+
+ /* Leading space. */
+ strcpy(buf," 1");
+ assert(string2ll(buf,strlen(buf),&v) == 0);
+
+ /* Trailing space. */
+ strcpy(buf,"1 ");
+ assert(string2ll(buf,strlen(buf),&v) == 0);
+
+ /* May not start with 0. */
+ strcpy(buf,"01");
+ assert(string2ll(buf,strlen(buf),&v) == 0);
+
+ strcpy(buf,"-1");
+ assert(string2ll(buf,strlen(buf),&v) == 1);
+ assert(v == -1);
+
+ strcpy(buf,"0");
+ assert(string2ll(buf,strlen(buf),&v) == 1);
+ assert(v == 0);
+
+ strcpy(buf,"1");
+ assert(string2ll(buf,strlen(buf),&v) == 1);
+ assert(v == 1);
+
+ strcpy(buf,"99");
+ assert(string2ll(buf,strlen(buf),&v) == 1);
+ assert(v == 99);
+
+ strcpy(buf,"-99");
+ assert(string2ll(buf,strlen(buf),&v) == 1);
+ assert(v == -99);
+
+ strcpy(buf,"-9223372036854775808");
+ assert(string2ll(buf,strlen(buf),&v) == 1);
+ assert(v == LLONG_MIN);
+
+ strcpy(buf,"-9223372036854775809"); /* overflow */
+ assert(string2ll(buf,strlen(buf),&v) == 0);
+
+ strcpy(buf,"9223372036854775807");
+ assert(string2ll(buf,strlen(buf),&v) == 1);
+ assert(v == LLONG_MAX);
+
+ strcpy(buf,"9223372036854775808"); /* overflow */
+ assert(string2ll(buf,strlen(buf),&v) == 0);