mirror of
https://github.com/fluencelabs/redis
synced 2025-06-14 17:51:21 +00:00
Merge remote-tracking branch 'upstream/unstable' into tls
This commit is contained in:
217
src/server.c
217
src/server.c
@ -1449,12 +1449,18 @@ int incrementallyRehash(int dbid) {
|
||||
* for dict.c to resize the hash tables accordingly to the fact we have o not
|
||||
* running childs. */
|
||||
void updateDictResizePolicy(void) {
|
||||
if (server.rdb_child_pid == -1 && server.aof_child_pid == -1)
|
||||
if (!hasActiveChildProcess())
|
||||
dictEnableResize();
|
||||
else
|
||||
dictDisableResize();
|
||||
}
|
||||
|
||||
int hasActiveChildProcess() {
|
||||
return server.rdb_child_pid != -1 ||
|
||||
server.aof_child_pid != -1 ||
|
||||
server.module_child_pid != -1;
|
||||
}
|
||||
|
||||
/* ======================= Cron: called every 100 ms ======================== */
|
||||
|
||||
/* Add a sample to the operations per second array of samples. */
|
||||
@ -1691,7 +1697,7 @@ void databasesCron(void) {
|
||||
/* Perform hash tables rehashing if needed, but only if there are no
|
||||
* other processes saving the DB on disk. Otherwise rehashing is bad
|
||||
* as will cause a lot of copy-on-write of memory pages. */
|
||||
if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) {
|
||||
if (!hasActiveChildProcess()) {
|
||||
/* We use global counters so if we stop the computation at a given
|
||||
* DB we'll be able to start from the successive in the next
|
||||
* cron loop iteration. */
|
||||
@ -1764,18 +1770,32 @@ void checkChildrenDone(void) {
|
||||
|
||||
if (WIFSIGNALED(statloc)) bysignal = WTERMSIG(statloc);
|
||||
|
||||
/* sigKillChildHandler catches the signal and calls exit(), but we
|
||||
* must make sure not to flag lastbgsave_status, etc incorrectly.
|
||||
* We could directly terminate the child process via SIGUSR1
|
||||
* without handling it, but in this case Valgrind will log an
|
||||
* annoying error. */
|
||||
if (exitcode == SERVER_CHILD_NOERROR_RETVAL) {
|
||||
bysignal = SIGUSR1;
|
||||
exitcode = 1;
|
||||
}
|
||||
|
||||
if (pid == -1) {
|
||||
serverLog(LL_WARNING,"wait3() returned an error: %s. "
|
||||
"rdb_child_pid = %d, aof_child_pid = %d",
|
||||
"rdb_child_pid = %d, aof_child_pid = %d, module_child_pid = %d",
|
||||
strerror(errno),
|
||||
(int) server.rdb_child_pid,
|
||||
(int) server.aof_child_pid);
|
||||
(int) server.aof_child_pid,
|
||||
(int) server.module_child_pid);
|
||||
} else if (pid == server.rdb_child_pid) {
|
||||
backgroundSaveDoneHandler(exitcode,bysignal);
|
||||
if (!bysignal && exitcode == 0) receiveChildInfo();
|
||||
} else if (pid == server.aof_child_pid) {
|
||||
backgroundRewriteDoneHandler(exitcode,bysignal);
|
||||
if (!bysignal && exitcode == 0) receiveChildInfo();
|
||||
} else if (pid == server.module_child_pid) {
|
||||
ModuleForkDoneHandler(exitcode,bysignal);
|
||||
if (!bysignal && exitcode == 0) receiveChildInfo();
|
||||
} else {
|
||||
if (!ldbRemoveChild(pid)) {
|
||||
serverLog(LL_WARNING,
|
||||
@ -1930,15 +1950,14 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
|
||||
|
||||
/* Start a scheduled AOF rewrite if this was requested by the user while
|
||||
* a BGSAVE was in progress. */
|
||||
if (server.rdb_child_pid == -1 && server.aof_child_pid == -1 &&
|
||||
if (!hasActiveChildProcess() &&
|
||||
server.aof_rewrite_scheduled)
|
||||
{
|
||||
rewriteAppendOnlyFileBackground();
|
||||
}
|
||||
|
||||
/* Check if a background saving or AOF rewrite in progress terminated. */
|
||||
if (server.rdb_child_pid != -1 || server.aof_child_pid != -1 ||
|
||||
ldbPendingChildren())
|
||||
if (hasActiveChildProcess() || ldbPendingChildren())
|
||||
{
|
||||
checkChildrenDone();
|
||||
} else {
|
||||
@ -1968,8 +1987,7 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
|
||||
|
||||
/* Trigger an AOF rewrite if needed. */
|
||||
if (server.aof_state == AOF_ON &&
|
||||
server.rdb_child_pid == -1 &&
|
||||
server.aof_child_pid == -1 &&
|
||||
!hasActiveChildProcess() &&
|
||||
server.aof_rewrite_perc &&
|
||||
server.aof_current_size > server.aof_rewrite_min_size)
|
||||
{
|
||||
@ -2027,7 +2045,7 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
|
||||
* Note: this code must be after the replicationCron() call above so
|
||||
* make sure when refactoring this file to keep this order. This is useful
|
||||
* because we want to give priority to RDB savings for replication. */
|
||||
if (server.rdb_child_pid == -1 && server.aof_child_pid == -1 &&
|
||||
if (!hasActiveChildProcess() &&
|
||||
server.rdb_bgsave_scheduled &&
|
||||
(server.unixtime-server.lastbgsave_try > CONFIG_BGSAVE_RETRY_DELAY ||
|
||||
server.lastbgsave_status == C_OK))
|
||||
@ -2261,6 +2279,7 @@ void initServerConfig(void) {
|
||||
server.maxidletime = CONFIG_DEFAULT_CLIENT_TIMEOUT;
|
||||
server.tcpkeepalive = CONFIG_DEFAULT_TCP_KEEPALIVE;
|
||||
server.active_expire_enabled = 1;
|
||||
server.jemalloc_bg_thread = 1;
|
||||
server.active_defrag_enabled = CONFIG_DEFAULT_ACTIVE_DEFRAG;
|
||||
server.active_defrag_ignore_bytes = CONFIG_DEFAULT_DEFRAG_IGNORE_BYTES;
|
||||
server.active_defrag_threshold_lower = CONFIG_DEFAULT_DEFRAG_THRESHOLD_LOWER;
|
||||
@ -2828,6 +2847,7 @@ void initServer(void) {
|
||||
server.cronloops = 0;
|
||||
server.rdb_child_pid = -1;
|
||||
server.aof_child_pid = -1;
|
||||
server.module_child_pid = -1;
|
||||
server.rdb_child_type = RDB_CHILD_TYPE_NONE;
|
||||
server.rdb_pipe_conns = NULL;
|
||||
server.rdb_pipe_numconns = 0;
|
||||
@ -2851,6 +2871,7 @@ void initServer(void) {
|
||||
server.stat_peak_memory = 0;
|
||||
server.stat_rdb_cow_bytes = 0;
|
||||
server.stat_aof_cow_bytes = 0;
|
||||
server.stat_module_cow_bytes = 0;
|
||||
server.cron_malloc_stats.zmalloc_used = 0;
|
||||
server.cron_malloc_stats.process_rss = 0;
|
||||
server.cron_malloc_stats.allocator_allocated = 0;
|
||||
@ -2926,8 +2947,17 @@ void initServer(void) {
|
||||
scriptingInit(1);
|
||||
slowlogInit();
|
||||
latencyMonitorInit();
|
||||
}
|
||||
|
||||
/* Some steps in server initialization need to be done last (after modules
|
||||
* are loaded).
|
||||
* Specifically, creation of threads due to a race bug in ld.so, in which
|
||||
* Thread Local Storage initialization collides with dlopen call.
|
||||
* see: https://sourceware.org/bugzilla/show_bug.cgi?id=19329 */
|
||||
void InitServerLast() {
|
||||
bioInit();
|
||||
initThreadedIO();
|
||||
set_jemalloc_bg_thread(server.jemalloc_bg_thread);
|
||||
server.initial_memory_usage = zmalloc_used_memory();
|
||||
}
|
||||
|
||||
@ -3383,11 +3413,12 @@ int processCommand(client *c) {
|
||||
|
||||
/* Check if the user is authenticated. This check is skipped in case
|
||||
* the default user is flagged as "nopass" and is active. */
|
||||
int auth_required = !(DefaultUser->flags & USER_FLAG_NOPASS) &&
|
||||
int auth_required = (!(DefaultUser->flags & USER_FLAG_NOPASS) ||
|
||||
DefaultUser->flags & USER_FLAG_DISABLED) &&
|
||||
!c->authenticated;
|
||||
if (auth_required || DefaultUser->flags & USER_FLAG_DISABLED) {
|
||||
if (auth_required) {
|
||||
/* AUTH and HELLO are valid even in non authenticated state. */
|
||||
if (c->cmd->proc != authCommand || c->cmd->proc == helloCommand) {
|
||||
if (c->cmd->proc != authCommand && c->cmd->proc != helloCommand) {
|
||||
flagTransaction(c);
|
||||
addReply(c,shared.noautherr);
|
||||
return C_OK;
|
||||
@ -3453,7 +3484,10 @@ int processCommand(client *c) {
|
||||
* is in MULTI/EXEC context? Error. */
|
||||
if (out_of_memory &&
|
||||
(c->cmd->flags & CMD_DENYOOM ||
|
||||
(c->flags & CLIENT_MULTI && c->cmd->proc != execCommand))) {
|
||||
(c->flags & CLIENT_MULTI &&
|
||||
c->cmd->proc != execCommand &&
|
||||
c->cmd->proc != discardCommand)))
|
||||
{
|
||||
flagTransaction(c);
|
||||
addReply(c, shared.oomerr);
|
||||
return C_OK;
|
||||
@ -3605,6 +3639,12 @@ int prepareForShutdown(int flags) {
|
||||
killRDBChild();
|
||||
}
|
||||
|
||||
/* Kill module child if there is one. */
|
||||
if (server.module_child_pid != -1) {
|
||||
serverLog(LL_WARNING,"There is a module fork child. Killing it!");
|
||||
TerminateModuleForkChild(server.module_child_pid,0);
|
||||
}
|
||||
|
||||
if (server.aof_state != AOF_OFF) {
|
||||
/* Kill the AOF saving child as the AOF we already have may be longer
|
||||
* but contains the full dataset anyway. */
|
||||
@ -3874,12 +3914,15 @@ sds genRedisInfoString(char *section) {
|
||||
time_t uptime = server.unixtime-server.stat_starttime;
|
||||
int j;
|
||||
struct rusage self_ru, c_ru;
|
||||
int allsections = 0, defsections = 0;
|
||||
int allsections = 0, defsections = 0, everything = 0, modules = 0;
|
||||
int sections = 0;
|
||||
|
||||
if (section == NULL) section = "default";
|
||||
allsections = strcasecmp(section,"all") == 0;
|
||||
defsections = strcasecmp(section,"default") == 0;
|
||||
everything = strcasecmp(section,"everything") == 0;
|
||||
modules = strcasecmp(section,"modules") == 0;
|
||||
if (everything) allsections = 1;
|
||||
|
||||
getrusage(RUSAGE_SELF, &self_ru);
|
||||
getrusage(RUSAGE_CHILDREN, &c_ru);
|
||||
@ -3902,32 +3945,32 @@ sds genRedisInfoString(char *section) {
|
||||
call_uname = 0;
|
||||
}
|
||||
|
||||
info = sdscatprintf(info,
|
||||
info = sdscatfmt(info,
|
||||
"# Server\r\n"
|
||||
"redis_version:%s\r\n"
|
||||
"redis_git_sha1:%s\r\n"
|
||||
"redis_git_dirty:%d\r\n"
|
||||
"redis_build_id:%llx\r\n"
|
||||
"redis_git_dirty:%i\r\n"
|
||||
"redis_build_id:%s\r\n"
|
||||
"redis_mode:%s\r\n"
|
||||
"os:%s %s %s\r\n"
|
||||
"arch_bits:%d\r\n"
|
||||
"arch_bits:%i\r\n"
|
||||
"multiplexing_api:%s\r\n"
|
||||
"atomicvar_api:%s\r\n"
|
||||
"gcc_version:%d.%d.%d\r\n"
|
||||
"process_id:%ld\r\n"
|
||||
"gcc_version:%i.%i.%i\r\n"
|
||||
"process_id:%I\r\n"
|
||||
"run_id:%s\r\n"
|
||||
"tcp_port:%d\r\n"
|
||||
"uptime_in_seconds:%jd\r\n"
|
||||
"uptime_in_days:%jd\r\n"
|
||||
"hz:%d\r\n"
|
||||
"configured_hz:%d\r\n"
|
||||
"lru_clock:%ld\r\n"
|
||||
"tcp_port:%i\r\n"
|
||||
"uptime_in_seconds:%I\r\n"
|
||||
"uptime_in_days:%I\r\n"
|
||||
"hz:%i\r\n"
|
||||
"configured_hz:%i\r\n"
|
||||
"lru_clock:%u\r\n"
|
||||
"executable:%s\r\n"
|
||||
"config_file:%s\r\n",
|
||||
REDIS_VERSION,
|
||||
redisGitSHA1(),
|
||||
strtol(redisGitDirty(),NULL,10) > 0,
|
||||
(unsigned long long) redisBuildId(),
|
||||
redisBuildIdString(),
|
||||
mode,
|
||||
name.sysname, name.release, name.machine,
|
||||
server.arch_bits,
|
||||
@ -3938,14 +3981,14 @@ sds genRedisInfoString(char *section) {
|
||||
#else
|
||||
0,0,0,
|
||||
#endif
|
||||
(long) getpid(),
|
||||
(int64_t) getpid(),
|
||||
server.runid,
|
||||
server.port ? server.port : server.tls_port,
|
||||
(intmax_t)uptime,
|
||||
(intmax_t)(uptime/(3600*24)),
|
||||
(int64_t)uptime,
|
||||
(int64_t)(uptime/(3600*24)),
|
||||
server.hz,
|
||||
server.config_hz,
|
||||
(unsigned long) server.lruclock,
|
||||
server.lruclock,
|
||||
server.executable ? server.executable : "",
|
||||
server.configfile ? server.configfile : "");
|
||||
}
|
||||
@ -4071,8 +4114,11 @@ sds genRedisInfoString(char *section) {
|
||||
mh->allocator_rss_bytes,
|
||||
mh->rss_extra,
|
||||
mh->rss_extra_bytes,
|
||||
mh->total_frag, /* this is the total RSS overhead, including fragmentation, */
|
||||
mh->total_frag_bytes, /* named so for backwards compatibility */
|
||||
mh->total_frag, /* This is the total RSS overhead, including
|
||||
fragmentation, but not just it. This field
|
||||
(and the next one) is named like that just
|
||||
for backward compatibility. */
|
||||
mh->total_frag_bytes,
|
||||
freeMemoryGetNotCountedMemory(),
|
||||
mh->repl_backlog,
|
||||
mh->clients_slaves,
|
||||
@ -4105,7 +4151,9 @@ sds genRedisInfoString(char *section) {
|
||||
"aof_current_rewrite_time_sec:%jd\r\n"
|
||||
"aof_last_bgrewrite_status:%s\r\n"
|
||||
"aof_last_write_status:%s\r\n"
|
||||
"aof_last_cow_size:%zu\r\n",
|
||||
"aof_last_cow_size:%zu\r\n"
|
||||
"module_fork_in_progress:%d\r\n"
|
||||
"module_fork_last_cow_size:%zu\r\n",
|
||||
server.loading,
|
||||
server.dirty,
|
||||
server.rdb_child_pid != -1,
|
||||
@ -4123,7 +4171,9 @@ sds genRedisInfoString(char *section) {
|
||||
-1 : time(NULL)-server.aof_rewrite_time_start),
|
||||
(server.aof_lastbgrewrite_status == C_OK) ? "ok" : "err",
|
||||
(server.aof_last_write_status == C_OK) ? "ok" : "err",
|
||||
server.stat_aof_cow_bytes);
|
||||
server.stat_aof_cow_bytes,
|
||||
server.module_child_pid != -1,
|
||||
server.stat_module_cow_bytes);
|
||||
|
||||
if (server.aof_enabled) {
|
||||
info = sdscatprintf(info,
|
||||
@ -4281,7 +4331,7 @@ sds genRedisInfoString(char *section) {
|
||||
if (server.repl_state != REPL_STATE_CONNECTED) {
|
||||
info = sdscatprintf(info,
|
||||
"master_link_down_since_seconds:%jd\r\n",
|
||||
(intmax_t)server.unixtime-server.repl_down_since);
|
||||
(intmax_t)(server.unixtime-server.repl_down_since));
|
||||
}
|
||||
info = sdscatprintf(info,
|
||||
"slave_priority:%d\r\n"
|
||||
@ -4379,6 +4429,13 @@ sds genRedisInfoString(char *section) {
|
||||
(long)c_ru.ru_utime.tv_sec, (long)c_ru.ru_utime.tv_usec);
|
||||
}
|
||||
|
||||
/* Modules */
|
||||
if (allsections || defsections || !strcasecmp(section,"modules")) {
|
||||
if (sections++) info = sdscat(info,"\r\n");
|
||||
info = sdscatprintf(info,"# Modules\r\n");
|
||||
info = genModulesInfoString(info);
|
||||
}
|
||||
|
||||
/* Command statistics */
|
||||
if (allsections || !strcasecmp(section,"commandstats")) {
|
||||
if (sections++) info = sdscat(info,"\r\n");
|
||||
@ -4424,6 +4481,17 @@ sds genRedisInfoString(char *section) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get info from modules.
|
||||
* if user asked for "everything" or "modules", or a specific section
|
||||
* that's not found yet. */
|
||||
if (everything || modules ||
|
||||
(!allsections && !defsections && sections==0)) {
|
||||
info = modulesCollectInfo(info,
|
||||
everything || modules ? NULL: section,
|
||||
0, /* not a crash report */
|
||||
sections);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
@ -4434,7 +4502,9 @@ void infoCommand(client *c) {
|
||||
addReply(c,shared.syntaxerr);
|
||||
return;
|
||||
}
|
||||
addReplyBulkSds(c, genRedisInfoString(section));
|
||||
sds info = genRedisInfoString(section);
|
||||
addReplyVerbatim(c,info,sdslen(info),"txt");
|
||||
sdsfree(info);
|
||||
}
|
||||
|
||||
void monitorCommand(client *c) {
|
||||
@ -4621,6 +4691,61 @@ void setupSignalHandlers(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* This is the signal handler for children process. It is currently useful
|
||||
* in order to track the SIGUSR1, that we send to a child in order to terminate
|
||||
* it in a clean way, without the parent detecting an error and stop
|
||||
* accepting writes because of a write error condition. */
|
||||
static void sigKillChildHandler(int sig) {
|
||||
UNUSED(sig);
|
||||
serverLogFromHandler(LL_WARNING, "Received SIGUSR1 in child, exiting now.");
|
||||
exitFromChild(SERVER_CHILD_NOERROR_RETVAL);
|
||||
}
|
||||
|
||||
void setupChildSignalHandlers(void) {
|
||||
struct sigaction act;
|
||||
|
||||
/* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction is used.
|
||||
* Otherwise, sa_handler is used. */
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = 0;
|
||||
act.sa_handler = sigKillChildHandler;
|
||||
sigaction(SIGUSR1, &act, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
int redisFork() {
|
||||
int childpid;
|
||||
long long start = ustime();
|
||||
if ((childpid = fork()) == 0) {
|
||||
/* Child */
|
||||
closeListeningSockets(0);
|
||||
setupChildSignalHandlers();
|
||||
} else {
|
||||
/* Parent */
|
||||
server.stat_fork_time = ustime()-start;
|
||||
server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */
|
||||
latencyAddSampleIfNeeded("fork",server.stat_fork_time/1000);
|
||||
if (childpid == -1) {
|
||||
return -1;
|
||||
}
|
||||
updateDictResizePolicy();
|
||||
}
|
||||
return childpid;
|
||||
}
|
||||
|
||||
void sendChildCOWInfo(int ptype, char *pname) {
|
||||
size_t private_dirty = zmalloc_get_private_dirty(-1);
|
||||
|
||||
if (private_dirty) {
|
||||
serverLog(LL_NOTICE,
|
||||
"%s: %zu MB of memory used by copy-on-write",
|
||||
pname, private_dirty/(1024*1024));
|
||||
}
|
||||
|
||||
server.child_info_data.cow_size = private_dirty;
|
||||
sendChildInfo(ptype);
|
||||
}
|
||||
|
||||
void memtest(size_t megabytes, int passes);
|
||||
|
||||
/* Returns 1 if there is --sentinel among the arguments or if
|
||||
@ -4647,12 +4772,14 @@ void loadDataFromDisk(void) {
|
||||
(float)(ustime()-start)/1000000);
|
||||
|
||||
/* Restore the replication ID / offset from the RDB file. */
|
||||
if ((server.masterhost || (server.cluster_enabled && nodeIsSlave(server.cluster->myself)))&&
|
||||
if ((server.masterhost ||
|
||||
(server.cluster_enabled &&
|
||||
nodeIsSlave(server.cluster->myself))) &&
|
||||
rsi.repl_id_is_set &&
|
||||
rsi.repl_offset != -1 &&
|
||||
/* Note that older implementations may save a repl_stream_db
|
||||
* of -1 inside the RDB file in a wrong way, see more information
|
||||
* in function rdbPopulateSaveInfo. */
|
||||
* of -1 inside the RDB file in a wrong way, see more
|
||||
* information in function rdbPopulateSaveInfo. */
|
||||
rsi.repl_stream_db != -1)
|
||||
{
|
||||
memcpy(server.replid,rsi.repl_id,sizeof(server.replid));
|
||||
@ -4828,9 +4955,9 @@ int main(int argc, char **argv) {
|
||||
srand(time(NULL)^getpid());
|
||||
gettimeofday(&tv,NULL);
|
||||
|
||||
char hashseed[16];
|
||||
getRandomHexChars(hashseed,sizeof(hashseed));
|
||||
dictSetHashFunctionSeed((uint8_t*)hashseed);
|
||||
uint8_t hashseed[16];
|
||||
getRandomBytes(hashseed,sizeof(hashseed));
|
||||
dictSetHashFunctionSeed(hashseed);
|
||||
server.sentinel_mode = checkForSentinelMode(argc,argv);
|
||||
initServerConfig();
|
||||
ACLInit(); /* The ACL subsystem must be initialized ASAP because the
|
||||
@ -4960,6 +5087,7 @@ int main(int argc, char **argv) {
|
||||
#endif
|
||||
moduleLoadFromQueue();
|
||||
ACLLoadUsersAtStartup();
|
||||
InitServerLast();
|
||||
loadDataFromDisk();
|
||||
if (server.cluster_enabled) {
|
||||
if (verifyClusterConfigWithData() == C_ERR) {
|
||||
@ -4974,6 +5102,7 @@ int main(int argc, char **argv) {
|
||||
if (server.sofd > 0)
|
||||
serverLog(LL_NOTICE,"The server is now ready to accept connections at %s", server.unixsocket);
|
||||
} else {
|
||||
InitServerLast();
|
||||
sentinelIsRunning();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user