Commit 96fbd433 authored by antirez's avatar antirez
Browse files

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.
parent 18711f18
...@@ -801,6 +801,8 @@ void createSharedObjects(void) { ...@@ -801,6 +801,8 @@ void createSharedObjects(void) {
} }
void initServerConfig() { 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.arch_bits = (sizeof(long) == 8) ? 64 : 32;
server.port = REDIS_SERVERPORT; server.port = REDIS_SERVERPORT;
server.bindaddr = NULL; server.bindaddr = NULL;
...@@ -1276,6 +1278,7 @@ sds genRedisInfoString(void) { ...@@ -1276,6 +1278,7 @@ sds genRedisInfoString(void) {
"multiplexing_api:%s\r\n" "multiplexing_api:%s\r\n"
"gcc_version:%d.%d.%d\r\n" "gcc_version:%d.%d.%d\r\n"
"process_id:%ld\r\n" "process_id:%ld\r\n"
"run_id:%s\r\n"
"uptime_in_seconds:%ld\r\n" "uptime_in_seconds:%ld\r\n"
"uptime_in_days:%ld\r\n" "uptime_in_days:%ld\r\n"
"lru_clock:%ld\r\n" "lru_clock:%ld\r\n"
...@@ -1323,6 +1326,7 @@ sds genRedisInfoString(void) { ...@@ -1323,6 +1326,7 @@ sds genRedisInfoString(void) {
0,0,0, 0,0,0,
#endif #endif
(long) getpid(), (long) getpid(),
server.runid,
uptime, uptime,
uptime/(3600*24), uptime/(3600*24),
(unsigned long) server.lruclock, (unsigned long) server.lruclock,
......
...@@ -61,6 +61,8 @@ ...@@ -61,6 +61,8 @@
#define REDIS_REPL_TIMEOUT 60 #define REDIS_REPL_TIMEOUT 60
#define REDIS_REPL_PING_SLAVE_PERIOD 10 #define REDIS_REPL_PING_SLAVE_PERIOD 10
#define REDIS_RUN_ID_SIZE 40
/* Hash table parameters */ /* Hash table parameters */
#define REDIS_HT_MINFILL 10 /* Minimal hash table fill 10% */ #define REDIS_HT_MINFILL 10 /* Minimal hash table fill 10% */
...@@ -408,6 +410,7 @@ struct redisServer { ...@@ -408,6 +410,7 @@ struct redisServer {
char neterr[ANET_ERR_LEN]; char neterr[ANET_ERR_LEN];
aeEventLoop *el; aeEventLoop *el;
int cronloops; /* number of times the cron function run */ 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 */ time_t lastsave; /* Unix time of last save succeeede */
/* Fields used only for stats */ /* Fields used only for stats */
time_t stat_starttime; /* server start time */ time_t stat_starttime; /* server start time */
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <math.h> #include <math.h>
#include <sys/time.h> #include <sys/time.h>
#include <float.h> #include <float.h>
#include <unistd.h>
#include "util.h" #include "util.h"
...@@ -329,6 +330,52 @@ int d2string(char *buf, size_t len, double value) { ...@@ -329,6 +330,52 @@ int d2string(char *buf, size_t len, double value) {
return len; 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 */ /* Return the UNIX time in microseconds */
long long ustime(void) { long long ustime(void) {
struct timeval tv; struct timeval tv;
......
...@@ -8,6 +8,7 @@ int ll2string(char *s, size_t len, long long value); ...@@ -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 string2ll(char *s, size_t slen, long long *value);
int string2l(char *s, size_t slen, long *value); int string2l(char *s, size_t slen, long *value);
int d2string(char *buf, size_t len, double value); int d2string(char *buf, size_t len, double value);
void getRandomHexChars(char *p, unsigned int len);
long long ustime(void); long long ustime(void);
long long mstime(void); long long mstime(void);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment