Implement use-fork config (fails with diskless repl)

Former-commit-id: f2d5c2bca22e9fd506db123c47b7f60cdded7e2c
This commit is contained in:
John Sully 2020-08-24 03:17:31 +00:00
parent 93a67abe52
commit ff9df842d8
5 changed files with 94 additions and 31 deletions

View File

@ -2308,6 +2308,7 @@ standardConfig configs[] = {
createBoolConfig("delete-on-evict", NULL, MODIFIABLE_CONFIG, cserver.delete_on_evict, 0, NULL, NULL),
createBoolConfig("io-threads-do-reads", NULL, IMMUTABLE_CONFIG, fDummy, 0,NULL, NULL), // Not applicable to KeyDB, just there for compatibility
createBoolConfig("multi-master-no-forward", NULL, MODIFIABLE_CONFIG, cserver.multimaster_no_forward, 0, validateMultiMasterNoForward, NULL),
createBoolConfig("use-fork", NULL, IMMUTABLE_CONFIG, cserver.fForkBgSave, 0, NULL, NULL),
/* String Configs */
createStringConfig("aclfile", NULL, IMMUTABLE_CONFIG, ALLOW_EMPTY_STRING, g_pserver->acl_filename, "", NULL, NULL),

View File

@ -1492,7 +1492,51 @@ void *rdbSaveThread(void *vargs)
return (retval == C_OK) ? (void*)0 : (void*)1;
}
int rdbSaveBackgroundFork(rdbSaveInfo *rsi) {
pid_t childpid;
if (hasActiveChildProcess() || g_pserver->rdb_child_pid != -1) return C_ERR;
serverAssert(g_pserver->rdb_child_pid != 10000);
g_pserver->dirty_before_bgsave = g_pserver->dirty;
g_pserver->lastbgsave_try = time(NULL);
openChildInfoPipe();
if ((childpid = redisFork()) == 0) {
int retval;
/* Child */
g_pserver->rdb_child_pid = 10000;
redisSetProcTitle("keydb-rdb-bgsave");
redisSetCpuAffinity(g_pserver->bgsave_cpulist);
retval = rdbSave(nullptr, rsi);
if (retval == C_OK) {
sendChildCOWInfo(CHILD_INFO_TYPE_RDB, "RDB");
}
exitFromChild((retval == C_OK) ? 0 : 1);
} else {
/* Parent */
if (childpid == -1) {
closeChildInfoPipe();
g_pserver->lastbgsave_status = C_ERR;
serverLog(LL_WARNING,"Can't save in background: fork: %s",
strerror(errno));
return C_ERR;
}
serverLog(LL_NOTICE,"Background saving started by pid %d",childpid);
g_pserver->rdb_save_time_start = time(NULL);
g_pserver->rdb_child_pid = childpid;
g_pserver->rdb_child_type = RDB_CHILD_TYPE_DISK;
return C_OK;
}
return C_OK; /* unreached */
}
int launchRdbSaveThread(pthread_t &child, rdbSaveInfo *rsi)
{
if (cserver.fForkBgSave) {
return rdbSaveBackgroundFork(rsi);
} else
{
rdbSaveThreadArgs *args = (rdbSaveThreadArgs*)zmalloc(sizeof(rdbSaveThreadArgs) + ((cserver.dbnum-1)*sizeof(redisDbPersistentDataSnapshot*)), MALLOC_LOCAL);
rdbSaveInfo rsiT = RDB_SAVE_INFO_INIT;
@ -1513,9 +1557,11 @@ int launchRdbSaveThread(pthread_t &child, rdbSaveInfo *rsi)
zfree(args);
return C_ERR;
}
}
return C_OK;
}
int rdbSaveBackground(rdbSaveInfo *rsi) {
pthread_t child;
long long start;
@ -2743,6 +2789,13 @@ void backgroundSaveDoneHandler(int exitcode, bool fCancelled) {
* the cleanup needed. */
void killRDBChild(bool fSynchronous) {
serverAssert(GlobalLocksAcquired());
if (cserver.fForkBgSave) {
kill(g_pserver->rdb_child_pid,SIGUSR1);
rdbRemoveTempFile(g_pserver->rdb_child_pid);
closeChildInfoPipe();
updateDictResizePolicy();
} else {
g_pserver->rdbThreadVars.fRdbThreadCancel = true;
rdbRemoveTempFile(g_pserver->rdbThreadVars.tmpfileNum);
closeChildInfoPipe();
@ -2757,6 +2810,7 @@ void killRDBChild(bool fSynchronous) {
aeAcquireLock();
}
}
}
struct rdbSaveSocketThreadArgs
{

View File

@ -1554,7 +1554,7 @@ int redisDbPersistentData::incrementallyRehash() {
* for dict.c to resize the hash tables accordingly to the fact we have o not
* running childs. */
void updateDictResizePolicy(void) {
if (!hasActiveChildProcess() || g_pserver->FRdbSaveInProgress())
if (!hasActiveChildProcess() || (g_pserver->FRdbSaveInProgress() && !cserver.fForkBgSave))
dictEnableResize();
else
dictDisableResize();
@ -1946,7 +1946,7 @@ void checkChildrenDone(void) {
if (g_pserver->FRdbSaveInProgress() && g_pserver->rdb_pipe_conns)
return;
if (g_pserver->FRdbSaveInProgress())
if (g_pserver->FRdbSaveInProgress() && !cserver.fForkBgSave)
{
void *rval = nullptr;
int err;
@ -1985,6 +1985,11 @@ void checkChildrenDone(void) {
strerror(errno),
(int) g_pserver->aof_child_pid,
(int) g_pserver->module_child_pid);
} else if (pid == g_pserver->rdb_child_pid) {
backgroundSaveDoneHandler(exitcode,bysignal == SIGUSR1);
g_pserver->rdbThreadVars.fRdbThreadCancel = false;
g_pserver->rdb_child_pid = -1;
if (exitcode == 0) receiveChildInfo();
} else if (pid == g_pserver->aof_child_pid) {
backgroundRewriteDoneHandler(exitcode,bysignal);
if (!bysignal && exitcode == 0) receiveChildInfo();

View File

@ -2130,6 +2130,7 @@ struct redisServerConst {
int multimaster_no_forward;
int storage_memory_model = STORAGE_WRITETHROUGH;
char *storage_conf = nullptr;
int fForkBgSave = false;
};
struct redisServer {
@ -2297,6 +2298,7 @@ struct redisServer {
time_t lastbgsave_try; /* Unix time of last attempted bgsave */
time_t rdb_save_time_last; /* Time used by last RDB save run. */
time_t rdb_save_time_start; /* Current RDB save start time. */
pid_t rdb_child_pid = -1; /* Used only during fork bgsave */
int rdb_bgsave_scheduled; /* BGSAVE when possible if true. */
int rdb_child_type; /* Type of save by active child. */
int lastbgsave_status; /* C_OK or C_ERR */

View File

@ -101,6 +101,7 @@ start_server {tags {"introspection"}} {
bgsave_cpulist
storage-cache-mode
storage-provider-options
use-fork
}
set configs {}