Tests are passing! YAY!
Former-commit-id: e300f753c58fc542267536cd90c1a6b970d83539
This commit is contained in:
parent
5d3c28a902
commit
6d05a34ddd
@ -857,6 +857,10 @@ void loadServerConfigFromString(char *config) {
|
|||||||
server.fActiveReplica = CONFIG_DEFAULT_ACTIVE_REPLICA;
|
server.fActiveReplica = CONFIG_DEFAULT_ACTIVE_REPLICA;
|
||||||
err = "argument must be 'yes' or 'no'"; goto loaderr;
|
err = "argument must be 'yes' or 'no'"; goto loaderr;
|
||||||
}
|
}
|
||||||
|
} else if (!strcasecmp(argv[0],"multi-master") && argc == 2){
|
||||||
|
if ((server.enable_multimaster = yesnotoi(argv[1])) == -1) {
|
||||||
|
err = "argument must be 'yes' or 'no'"; goto loaderr;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
err = "Bad directive or wrong number of arguments"; goto loaderr;
|
err = "Bad directive or wrong number of arguments"; goto loaderr;
|
||||||
}
|
}
|
||||||
@ -1336,6 +1340,8 @@ void configSetCommand(client *c) {
|
|||||||
"loglevel",server.verbosity,loglevel_enum) {
|
"loglevel",server.verbosity,loglevel_enum) {
|
||||||
} config_set_enum_field(
|
} config_set_enum_field(
|
||||||
"maxmemory-policy",server.maxmemory_policy,maxmemory_policy_enum) {
|
"maxmemory-policy",server.maxmemory_policy,maxmemory_policy_enum) {
|
||||||
|
} config_set_bool_field(
|
||||||
|
"multi-master", server.enable_multimaster) {
|
||||||
} config_set_enum_field(
|
} config_set_enum_field(
|
||||||
"appendfsync",server.aof_fsync,aof_fsync_enum) {
|
"appendfsync",server.aof_fsync,aof_fsync_enum) {
|
||||||
|
|
||||||
@ -2378,6 +2384,7 @@ int rewriteConfig(char *path) {
|
|||||||
rewriteConfigYesNoOption(state,"replica-lazy-flush",server.repl_slave_lazy_flush,CONFIG_DEFAULT_SLAVE_LAZY_FLUSH);
|
rewriteConfigYesNoOption(state,"replica-lazy-flush",server.repl_slave_lazy_flush,CONFIG_DEFAULT_SLAVE_LAZY_FLUSH);
|
||||||
rewriteConfigYesNoOption(state,"dynamic-hz",server.dynamic_hz,CONFIG_DEFAULT_DYNAMIC_HZ);
|
rewriteConfigYesNoOption(state,"dynamic-hz",server.dynamic_hz,CONFIG_DEFAULT_DYNAMIC_HZ);
|
||||||
rewriteConfigYesNoOption(state,"active-replica",server.fActiveReplica,CONFIG_DEFAULT_ACTIVE_REPLICA);
|
rewriteConfigYesNoOption(state,"active-replica",server.fActiveReplica,CONFIG_DEFAULT_ACTIVE_REPLICA);
|
||||||
|
rewriteConfigYesNoOption(state,"multi-master",server.enable_multimaster,CONFIG_DEFAULT_ENABLE_MULTIMASTER);
|
||||||
|
|
||||||
/* Rewrite Sentinel config if in Sentinel mode. */
|
/* Rewrite Sentinel config if in Sentinel mode. */
|
||||||
if (server.sentinel_mode) rewriteConfigSentinelOption(state);
|
if (server.sentinel_mode) rewriteConfigSentinelOption(state);
|
||||||
|
@ -1231,6 +1231,7 @@ void replicationEmptyDbCallback(void *privdata) {
|
|||||||
* performed, this function materializes the master client we store
|
* performed, this function materializes the master client we store
|
||||||
* at server.master, starting from the specified file descriptor. */
|
* at server.master, starting from the specified file descriptor. */
|
||||||
void replicationCreateMasterClient(redisMaster *mi, int fd, int dbid) {
|
void replicationCreateMasterClient(redisMaster *mi, int fd, int dbid) {
|
||||||
|
serverAssert(mi->master == nullptr);
|
||||||
mi->master = createClient(fd, serverTL - server.rgthreadvar);
|
mi->master = createClient(fd, serverTL - server.rgthreadvar);
|
||||||
mi->master->flags |= CLIENT_MASTER;
|
mi->master->flags |= CLIENT_MASTER;
|
||||||
mi->master->authenticated = 1;
|
mi->master->authenticated = 1;
|
||||||
@ -1248,8 +1249,6 @@ void replicationCreateMasterClient(redisMaster *mi, int fd, int dbid) {
|
|||||||
if (mi->master->reploff == -1)
|
if (mi->master->reploff == -1)
|
||||||
mi->master->flags |= CLIENT_PRE_PSYNC;
|
mi->master->flags |= CLIENT_PRE_PSYNC;
|
||||||
if (dbid != -1) selectDb(mi->master,dbid);
|
if (dbid != -1) selectDb(mi->master,dbid);
|
||||||
|
|
||||||
listAddNodeTail(server.masters, mi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function will try to re-enable the AOF file after the
|
/* This function will try to re-enable the AOF file after the
|
||||||
@ -2163,9 +2162,29 @@ int cancelReplicationHandshake(redisMaster *mi) {
|
|||||||
|
|
||||||
/* Set replication to the specified master address and port. */
|
/* Set replication to the specified master address and port. */
|
||||||
struct redisMaster *replicationAddMaster(char *ip, int port) {
|
struct redisMaster *replicationAddMaster(char *ip, int port) {
|
||||||
redisMaster *mi = (redisMaster*)zcalloc(sizeof(redisMaster), MALLOC_LOCAL);
|
// pre-reqs: We must not already have a replica in the list with the same tuple
|
||||||
initMasterInfo(mi);
|
listIter li;
|
||||||
int was_master = mi->masterhost == NULL;
|
listNode *ln;
|
||||||
|
listRewind(server.masters, &li);
|
||||||
|
while ((ln = listNext(&li)))
|
||||||
|
{
|
||||||
|
redisMaster *miCheck = (redisMaster*)listNodeValue(ln);
|
||||||
|
serverAssert(strcasecmp(miCheck->masterhost, ip) || miCheck->masterport != port);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pre-req satisfied, lets continue
|
||||||
|
int was_master = listLength(server.masters) == 0;
|
||||||
|
redisMaster *mi = nullptr;
|
||||||
|
if (!server.enable_multimaster && listLength(server.masters)) {
|
||||||
|
serverAssert(listLength(server.masters) == 1);
|
||||||
|
mi = (redisMaster*)listNodeValue(listFirst(server.masters));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mi = (redisMaster*)zcalloc(sizeof(redisMaster), MALLOC_LOCAL);
|
||||||
|
initMasterInfo(mi);
|
||||||
|
listAddNodeTail(server.masters, mi);
|
||||||
|
}
|
||||||
|
|
||||||
sdsfree(mi->masterhost);
|
sdsfree(mi->masterhost);
|
||||||
mi->masterhost = sdsnew(ip);
|
mi->masterhost = sdsnew(ip);
|
||||||
@ -2186,14 +2205,14 @@ struct redisMaster *replicationAddMaster(char *ip, int port) {
|
|||||||
* our own parameters, to later PSYNC with the new master. */
|
* our own parameters, to later PSYNC with the new master. */
|
||||||
if (was_master) replicationCacheMasterUsingMyself(mi);
|
if (was_master) replicationCacheMasterUsingMyself(mi);
|
||||||
mi->repl_state = REPL_STATE_CONNECT;
|
mi->repl_state = REPL_STATE_CONNECT;
|
||||||
listAddNodeTail(server.masters, mi);
|
|
||||||
return mi;
|
return mi;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cancel replication, setting the instance as a master itself. */
|
/* Cancel replication, setting the instance as a master itself. */
|
||||||
void replicationUnsetMaster(redisMaster *mi) {
|
void replicationUnsetMaster(redisMaster *mi) {
|
||||||
if (mi->masterhost == NULL) return; /* Nothing to do. */
|
serverAssert(mi->masterhost != NULL);
|
||||||
sdsfree(mi->masterhost);
|
sdsfree(mi->masterhost);
|
||||||
|
|
||||||
mi->masterhost = NULL;
|
mi->masterhost = NULL;
|
||||||
/* When a slave is turned into a master, the current replication ID
|
/* When a slave is turned into a master, the current replication ID
|
||||||
* (that was inherited from the master at synchronization time) is
|
* (that was inherited from the master at synchronization time) is
|
||||||
@ -2226,6 +2245,10 @@ void replicationUnsetMaster(redisMaster *mi) {
|
|||||||
* starting from now. Otherwise the backlog will be freed after a
|
* starting from now. Otherwise the backlog will be freed after a
|
||||||
* failover if slaves do not connect immediately. */
|
* failover if slaves do not connect immediately. */
|
||||||
server.repl_no_slaves_since = server.unixtime;
|
server.repl_no_slaves_since = server.unixtime;
|
||||||
|
|
||||||
|
listNode *ln = listSearchKey(server.masters, mi);
|
||||||
|
serverAssert(ln != nullptr);
|
||||||
|
listDelNode(server.masters, ln);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function is called when the slave lose the connection with the
|
/* This function is called when the slave lose the connection with the
|
||||||
@ -2252,12 +2275,9 @@ void replicaofCommand(client *c) {
|
|||||||
if (!strcasecmp((const char*)ptrFromObj(c->argv[1]),"no") &&
|
if (!strcasecmp((const char*)ptrFromObj(c->argv[1]),"no") &&
|
||||||
!strcasecmp((const char*)ptrFromObj(c->argv[2]),"one")) {
|
!strcasecmp((const char*)ptrFromObj(c->argv[2]),"one")) {
|
||||||
if (listLength(server.masters)) {
|
if (listLength(server.masters)) {
|
||||||
listIter li;
|
while (listLength(server.masters))
|
||||||
listNode *ln;
|
|
||||||
listRewind(server.masters, &li);
|
|
||||||
while ((ln = listNext(&li)))
|
|
||||||
{
|
{
|
||||||
replicationUnsetMaster((redisMaster*)listNodeValue(ln));
|
replicationUnsetMaster((redisMaster*)listNodeValue(listFirst(server.masters)));
|
||||||
}
|
}
|
||||||
sds client = catClientInfoString(sdsempty(),c);
|
sds client = catClientInfoString(sdsempty(),c);
|
||||||
serverLog(LL_NOTICE,"MASTER MODE enabled (user request from '%s')",
|
serverLog(LL_NOTICE,"MASTER MODE enabled (user request from '%s')",
|
||||||
|
@ -2279,6 +2279,9 @@ void initServerConfig(void) {
|
|||||||
server.runid[CONFIG_RUN_ID_SIZE] = '\0';
|
server.runid[CONFIG_RUN_ID_SIZE] = '\0';
|
||||||
changeReplicationId();
|
changeReplicationId();
|
||||||
clearReplicationId2();
|
clearReplicationId2();
|
||||||
|
server.clients = listCreate();
|
||||||
|
server.slaves = listCreate();
|
||||||
|
server.monitors = listCreate();
|
||||||
server.timezone = getTimeZone(); /* Initialized by tzset(). */
|
server.timezone = getTimeZone(); /* Initialized by tzset(). */
|
||||||
server.configfile = NULL;
|
server.configfile = NULL;
|
||||||
server.executable = NULL;
|
server.executable = NULL;
|
||||||
@ -2397,6 +2400,7 @@ void initServerConfig(void) {
|
|||||||
|
|
||||||
/* Replication related */
|
/* Replication related */
|
||||||
server.masters = listCreate();
|
server.masters = listCreate();
|
||||||
|
server.enable_multimaster = CONFIG_DEFAULT_ENABLE_MULTIMASTER;
|
||||||
server.repl_syncio_timeout = CONFIG_REPL_SYNCIO_TIMEOUT;
|
server.repl_syncio_timeout = CONFIG_REPL_SYNCIO_TIMEOUT;
|
||||||
server.repl_serve_stale_data = CONFIG_DEFAULT_SLAVE_SERVE_STALE_DATA;
|
server.repl_serve_stale_data = CONFIG_DEFAULT_SLAVE_SERVE_STALE_DATA;
|
||||||
server.repl_slave_ro = CONFIG_DEFAULT_SLAVE_READ_ONLY;
|
server.repl_slave_ro = CONFIG_DEFAULT_SLAVE_READ_ONLY;
|
||||||
@ -2858,11 +2862,8 @@ void initServer(void) {
|
|||||||
server.hz = server.config_hz;
|
server.hz = server.config_hz;
|
||||||
server.pid = getpid();
|
server.pid = getpid();
|
||||||
server.current_client = NULL;
|
server.current_client = NULL;
|
||||||
server.clients = listCreate();
|
|
||||||
server.clients_index = raxNew();
|
server.clients_index = raxNew();
|
||||||
server.clients_to_close = listCreate();
|
server.clients_to_close = listCreate();
|
||||||
server.slaves = listCreate();
|
|
||||||
server.monitors = listCreate();
|
|
||||||
server.slaveseldb = -1; /* Force to emit the first SELECT command. */
|
server.slaveseldb = -1; /* Force to emit the first SELECT command. */
|
||||||
server.ready_keys = listCreate();
|
server.ready_keys = listCreate();
|
||||||
server.clients_waiting_acks = listCreate();
|
server.clients_waiting_acks = listCreate();
|
||||||
|
@ -188,6 +188,7 @@ extern "C" {
|
|||||||
#define CONFIG_DEFAULT_THREAD_AFFINITY 0
|
#define CONFIG_DEFAULT_THREAD_AFFINITY 0
|
||||||
|
|
||||||
#define CONFIG_DEFAULT_ACTIVE_REPLICA 0
|
#define CONFIG_DEFAULT_ACTIVE_REPLICA 0
|
||||||
|
#define CONFIG_DEFAULT_ENABLE_MULTIMASTER 0
|
||||||
|
|
||||||
#define ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 20 /* Loopkups per loop. */
|
#define ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 20 /* Loopkups per loop. */
|
||||||
#define ACTIVE_EXPIRE_CYCLE_FAST_DURATION 1000 /* Microseconds */
|
#define ACTIVE_EXPIRE_CYCLE_FAST_DURATION 1000 /* Microseconds */
|
||||||
@ -1326,6 +1327,7 @@ struct redisServer {
|
|||||||
int repl_diskless_sync_delay; /* Delay to start a diskless repl BGSAVE. */
|
int repl_diskless_sync_delay; /* Delay to start a diskless repl BGSAVE. */
|
||||||
/* Replication (slave) */
|
/* Replication (slave) */
|
||||||
list *masters;
|
list *masters;
|
||||||
|
int enable_multimaster;
|
||||||
int repl_timeout; /* Timeout after N seconds of master idle */
|
int repl_timeout; /* Timeout after N seconds of master idle */
|
||||||
int repl_syncio_timeout; /* Timeout for synchronous I/O calls */
|
int repl_syncio_timeout; /* Timeout for synchronous I/O calls */
|
||||||
int repl_disable_tcp_nodelay; /* Disable TCP_NODELAY after SYNC? */
|
int repl_disable_tcp_nodelay; /* Disable TCP_NODELAY after SYNC? */
|
||||||
|
@ -48,7 +48,7 @@ proc warnings_from_file {filename} {
|
|||||||
|
|
||||||
# Return value for INFO property
|
# Return value for INFO property
|
||||||
proc status {r property} {
|
proc status {r property} {
|
||||||
if {[regexp "\r\n$property:(.*?)\r\n" [{*}$r info] _ value]} {
|
if {[regexp "\r\n(\t*?)$property:(.*?)\r\n" [{*}$r info] _ __ value]} {
|
||||||
set _ $value
|
set _ $value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user