summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/redis.c4
-rw-r--r--src/redis.h3
-rw-r--r--src/util.c47
-rw-r--r--src/util.h1
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);