From 44f508f1a81941f298bdb0f2f87c4469094beeb6 Mon Sep 17 00:00:00 2001 From: antirez Date: Thu, 8 Mar 2012 10:08:44 +0100 Subject: [PATCH] clusterGetRandomName() generalized into getRandomHexChars() so that we can use it for the run_id field as well. --- src/cluster.c | 16 +--------------- src/redis.h | 3 +++ src/util.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 15 deletions(-) diff --git a/src/cluster.c b/src/cluster.c index 85cb11981100..f76e8ff5cf8b 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -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; diff --git a/src/redis.h b/src/redis.h index fdf7f08d335c..3ecedd4caee2 100644 --- a/src/redis.h +++ b/src/redis.h @@ -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); diff --git a/src/util.c b/src/util.c index f5a23af2aeac..b6ec2150d8db 100644 --- a/src/util.c +++ b/src/util.c @@ -5,6 +5,8 @@ #include #include #include +#include +#include #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