summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2012-03-08 10:13:12 +0100
committerantirez <antirez@gmail.com>2012-08-30 14:52:29 +0200
commit96fbd4333f487b8a6fd311ba0ca2edc504f97d3b (patch)
treedf402172434a04bb526a421e27639ff54206904f
parent18711f1878f462d9a454a4e4e92518cd3df39af2 (diff)
downloadredis-96fbd4333f487b8a6fd311ba0ca2edc504f97d3b.tar.gz
run_id added to INFO output (backported from 2.6).
This change is required to make Redis 2.4 compatible with Sentinel. The Run ID is a field that identifies a single execution of the Redis server. It can be useful for many purposes as it makes easy to detect if the instance we are talking about is the same, or if it is a different one or was rebooted. An application of run_id will be in the partial synchronization of replication, where a slave may request a partial sync from a given offset only if it is talking with the same master. Another application is in failover and monitoring scripts.
-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);