diff options
-rw-r--r-- | src/redis.c | 4 | ||||
-rw-r--r-- | src/redis.h | 3 | ||||
-rw-r--r-- | src/util.c | 47 | ||||
-rw-r--r-- | src/util.h | 1 |
4 files changed, 55 insertions, 0 deletions
diff --git a/src/redis.c b/src/redis.c index 3267744d2..f43555446 100644 --- a/src/redis.c +++ b/src/redis.c @@ -801,6 +801,8 @@ void createSharedObjects(void) { } void initServerConfig() { + getRandomHexChars(server.runid,REDIS_RUN_ID_SIZE); + server.runid[REDIS_RUN_ID_SIZE] = '\0'; server.arch_bits = (sizeof(long) == 8) ? 64 : 32; server.port = REDIS_SERVERPORT; server.bindaddr = NULL; @@ -1276,6 +1278,7 @@ sds genRedisInfoString(void) { "multiplexing_api:%s\r\n" "gcc_version:%d.%d.%d\r\n" "process_id:%ld\r\n" + "run_id:%s\r\n" "uptime_in_seconds:%ld\r\n" "uptime_in_days:%ld\r\n" "lru_clock:%ld\r\n" @@ -1323,6 +1326,7 @@ sds genRedisInfoString(void) { 0,0,0, #endif (long) getpid(), + server.runid, uptime, uptime/(3600*24), (unsigned long) server.lruclock, diff --git a/src/redis.h b/src/redis.h index 34b58d467..5eb67adf2 100644 --- a/src/redis.h +++ b/src/redis.h @@ -61,6 +61,8 @@ #define REDIS_REPL_TIMEOUT 60 #define REDIS_REPL_PING_SLAVE_PERIOD 10 +#define REDIS_RUN_ID_SIZE 40 + /* Hash table parameters */ #define REDIS_HT_MINFILL 10 /* Minimal hash table fill 10% */ @@ -408,6 +410,7 @@ struct redisServer { char neterr[ANET_ERR_LEN]; aeEventLoop *el; int cronloops; /* number of times the cron function run */ + char runid[REDIS_RUN_ID_SIZE+1]; /* ID always different at every exec. */ time_t lastsave; /* Unix time of last save succeeede */ /* Fields used only for stats */ time_t stat_starttime; /* server start time */ diff --git a/src/util.c b/src/util.c index e24cde2b8..6016d2d8c 100644 --- a/src/util.c +++ b/src/util.c @@ -7,6 +7,7 @@ #include <math.h> #include <sys/time.h> #include <float.h> +#include <unistd.h> #include "util.h" @@ -329,6 +330,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); +} + /* Return the UNIX time in microseconds */ long long ustime(void) { struct timeval tv; diff --git a/src/util.h b/src/util.h index 85e4ddc6f..905c4f959 100644 --- a/src/util.h +++ b/src/util.h @@ -8,6 +8,7 @@ int ll2string(char *s, size_t len, long long value); int string2ll(char *s, size_t slen, long long *value); int string2l(char *s, size_t slen, long *value); int d2string(char *buf, size_t len, double value); +void getRandomHexChars(char *p, unsigned int len); long long ustime(void); long long mstime(void); |