]> git.saurik.com Git - redis.git/commitdiff
clusterGetRandomName() generalized into getRandomHexChars() so that we can use it...
authorantirez <antirez@gmail.com>
Thu, 8 Mar 2012 09:08:44 +0000 (10:08 +0100)
committerantirez <antirez@gmail.com>
Thu, 8 Mar 2012 09:08:44 +0000 (10:08 +0100)
src/cluster.c
src/redis.h
src/util.c

index 85cb119811008fd770a46f2a46118089a6192b64..f76e8ff5cf8b1e57d9a1e363ecb8116ac1180bdb 100644 (file)
@@ -19,20 +19,6 @@ int clusterAddSlot(clusterNode *n, int slot);
  * Initialization
  * -------------------------------------------------------------------------- */
 
-void clusterGetRandomName(char *p) {
-    FILE *fp = fopen("/dev/urandom","r");
-    char *charset = "0123456789abcdef";
-    int j;
-
-    if (fp == NULL || fread(p,REDIS_CLUSTER_NAMELEN,1,fp) == 0) {
-        for (j = 0; j < REDIS_CLUSTER_NAMELEN; j++)
-            p[j] = rand();
-    }
-    for (j = 0; j < REDIS_CLUSTER_NAMELEN; j++)
-        p[j] = charset[p[j] & 0x0F];
-    fclose(fp);
-}
-
 int clusterLoadConfig(char *filename) {
     FILE *fp = fopen(filename,"r");
     char *line;
@@ -304,7 +290,7 @@ clusterNode *createClusterNode(char *nodename, int flags) {
     if (nodename)
         memcpy(node->name, nodename, REDIS_CLUSTER_NAMELEN);
     else
-        clusterGetRandomName(node->name);
+        getRandomHexChars(node->name, REDIS_CLUSTER_NAMELEN);
     node->flags = flags;
     memset(node->slots,0,sizeof(node->slots));
     node->numslaves = 0;
index fdf7f08d335ce75c2b89e5d0ca6ed92f72713ef3..3ecedd4caee200acbcfda329cbd33a68166c7680 100644 (file)
@@ -58,6 +58,8 @@
 #define REDIS_REPL_TIMEOUT 60
 #define REDIS_REPL_PING_SLAVE_PERIOD 10
 
+#define REDIS_RUN_ID_SIZE 40
+
 /* Protocol and I/O related defines */
 #define REDIS_MAX_QUERYBUF_LEN  (1024*1024*1024) /* 1GB max query buffer. */
 #define REDIS_IOBUF_LEN         (1024*16)  /* Generic I/O buffer size */
@@ -813,6 +815,7 @@ dictType hashDictType;
 /* Utils */
 long long ustime(void);
 long long mstime(void);
+void getRandomHexChars(char *p, unsigned int len);
 
 /* networking.c -- Networking and Client related operations */
 redisClient *createClient(int fd);
index f5a23af2aeacd50a31c906223b0355edb7379ef9..b6ec2150d8db5788c3e602249d85a81c0954b468 100644 (file)
@@ -5,6 +5,8 @@
 #include <ctype.h>
 #include <limits.h>
 #include <math.h>
+#include <unistd.h>
+#include <sys/time.h>
 
 #include "util.h"
 
@@ -327,6 +329,52 @@ int d2string(char *buf, size_t len, double value) {
     return len;
 }
 
+/* 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>