Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ae048a443 | ||
|
|
1c79b5d98c | ||
|
|
5daffe2cfc | ||
|
|
8cb68f235f | ||
|
|
13787a1187 |
No files matched your search
Vendored
+1
-1
@@ -95,7 +95,7 @@ JEMALLOC_LDFLAGS= $(LDFLAGS)
|
||||
|
||||
jemalloc: .make-prerequisites
|
||||
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)
|
||||
cd jemalloc && ./configure --with-version=5.2.1-0-g0 --with-lg-quantum=3 --disable-cxx CFLAGS="$(JEMALLOC_CFLAGS)" LDFLAGS="$(JEMALLOC_LDFLAGS)"
|
||||
cd jemalloc && ./configure --with-version=5.2.1-0-g0 --with-lg-quantum=3 --with-jemalloc-prefix=je_ --disable-cxx CFLAGS="$(JEMALLOC_CFLAGS)" LDFLAGS="$(JEMALLOC_LDFLAGS)"
|
||||
cd jemalloc && $(MAKE) CFLAGS="$(JEMALLOC_CFLAGS)" LDFLAGS="$(JEMALLOC_LDFLAGS)" lib/libjemalloc.a
|
||||
|
||||
.PHONY: jemalloc
|
||||
|
||||
Vendored
+1
-1
Submodule deps/rocksdb updated: 444b3f4845...e3169e3ea8.
+1
-1
@@ -25,7 +25,7 @@ NODEPS:=clean distclean
|
||||
|
||||
# Default settings
|
||||
STD=-pedantic -DREDIS_STATIC=''
|
||||
CXX_STD=-std=c++17 -pedantic -fno-rtti -D__STDC_FORMAT_MACROS
|
||||
CXX_STD=-std=c++14 -pedantic -fno-rtti -D__STDC_FORMAT_MACROS
|
||||
ifneq (,$(findstring clang,$(CC)))
|
||||
STD+=-Wno-c11-extensions
|
||||
else
|
||||
|
||||
@@ -140,7 +140,7 @@ void SnapshotPayloadParseState::flushQueuedKeys() {
|
||||
auto &insertsInFlightTmp = insertsInFlight; // C++ GRRRRRRRRRRRRRRRR, we don't want to capute "this" because that's dangerous
|
||||
if (current_database < cserver.dbnum) {
|
||||
g_pserver->asyncworkqueue->AddWorkFunction([idb, vecqueuedKeys = std::move(this->vecqueuedKeys), vecqueuedKeysCb = std::move(this->vecqueuedKeysCb), vecqueuedVals = std::move(this->vecqueuedVals), vecqueuedValsCb = std::move(this->vecqueuedValsCb), &insertsInFlightTmp, pallocator = m_spallocator.release()]() mutable {
|
||||
g_pserver->db[idb]->bulkDirectStorageInsert(vecqueuedKeys.data(), vecqueuedKeysCb.data(), vecqueuedVals.data(), vecqueuedValsCb.data(), vecqueuedKeys.size());
|
||||
g_pserver->db[idb]->bulkStorageInsert(vecqueuedKeys.data(), vecqueuedKeysCb.data(), vecqueuedVals.data(), vecqueuedValsCb.data(), vecqueuedKeys.size());
|
||||
--insertsInFlightTmp;
|
||||
delete pallocator;
|
||||
});
|
||||
|
||||
@@ -42,7 +42,6 @@ typedef struct {
|
||||
* RDB / AOF saving process from the child to the parent (for instance
|
||||
* the amount of copy on write memory used) */
|
||||
void openChildInfoPipe(void) {
|
||||
serverAssert(g_pserver->child_info_pipe[0] == -1);
|
||||
if (pipe(g_pserver->child_info_pipe) == -1) {
|
||||
/* On error our two file descriptors should be still set to -1,
|
||||
* but we call anyway closeChildInfoPipe() since can't hurt. */
|
||||
|
||||
+1
-29
@@ -35,7 +35,6 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#ifdef __linux__
|
||||
#include <sys/sysinfo.h>
|
||||
#endif
|
||||
@@ -2457,32 +2456,6 @@ static int isValidAOFfilename(char *val, const char **err) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int isValidS3Bucket(char *s3bucket, const char **err) {
|
||||
int status = EXIT_FAILURE;
|
||||
pid_t pid = fork();
|
||||
if (pid < 0)
|
||||
{
|
||||
*err = "couldn't fork to call aws cli";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
execlp("aws", "aws", "s3", "ls", s3bucket);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
waitpid(pid, &status, 0);
|
||||
}
|
||||
|
||||
if (status != EXIT_SUCCESS) {
|
||||
*err = "could not access s3 bucket";
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Validate specified string is a valid proc-title-template */
|
||||
static int isValidProcTitleTemplate(char *val, const char **err) {
|
||||
if (!validateProcTitleTemplate(val)) {
|
||||
@@ -2806,7 +2779,7 @@ standardConfig configs[] = {
|
||||
createBoolConfig("appendonly", NULL, MODIFIABLE_CONFIG, g_pserver->aof_enabled, 0, NULL, updateAppendonly),
|
||||
createBoolConfig("cluster-allow-reads-when-down", NULL, MODIFIABLE_CONFIG, g_pserver->cluster_allow_reads_when_down, 0, NULL, NULL),
|
||||
createBoolConfig("delete-on-evict", NULL, MODIFIABLE_CONFIG, cserver.delete_on_evict, 0, NULL, NULL),
|
||||
createBoolConfig("use-fork", NULL, IMMUTABLE_CONFIG, cserver.fForkBgSave, 1, NULL, NULL),
|
||||
createBoolConfig("use-fork", NULL, IMMUTABLE_CONFIG, cserver.fForkBgSave, 0, NULL, NULL),
|
||||
createBoolConfig("io-threads-do-reads", NULL, IMMUTABLE_CONFIG, fDummy, 0, NULL, NULL),
|
||||
createBoolConfig("time-thread-priority", NULL, IMMUTABLE_CONFIG, cserver.time_thread_priority, 0, NULL, NULL),
|
||||
createBoolConfig("prefetch-enabled", NULL, MODIFIABLE_CONFIG, g_pserver->prefetch_enabled, 1, NULL, NULL),
|
||||
@@ -2830,7 +2803,6 @@ standardConfig configs[] = {
|
||||
createStringConfig("cluster-announce-ip", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, g_pserver->cluster_announce_ip, NULL, NULL, NULL),
|
||||
createStringConfig("syslog-ident", NULL, IMMUTABLE_CONFIG, ALLOW_EMPTY_STRING, g_pserver->syslog_ident, "redis", NULL, NULL),
|
||||
createStringConfig("dbfilename", NULL, MODIFIABLE_CONFIG, ALLOW_EMPTY_STRING, g_pserver->rdb_filename, CONFIG_DEFAULT_RDB_FILENAME, isValidDBfilename, NULL),
|
||||
createStringConfig("db-s3-object", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, g_pserver->rdb_s3bucketpath, NULL, isValidS3Bucket, NULL),
|
||||
createStringConfig("appendfilename", NULL, IMMUTABLE_CONFIG, ALLOW_EMPTY_STRING, g_pserver->aof_filename, "appendonly.aof", isValidAOFfilename, NULL),
|
||||
createStringConfig("server_cpulist", NULL, IMMUTABLE_CONFIG, EMPTY_STRING_IS_NULL, g_pserver->server_cpulist, NULL, NULL, NULL),
|
||||
createStringConfig("bio_cpulist", NULL, IMMUTABLE_CONFIG, EMPTY_STRING_IS_NULL, g_pserver->bio_cpulist, NULL, NULL, NULL),
|
||||
|
||||
+9
-28
@@ -1931,7 +1931,6 @@ void setExpire(client *c, redisDb *db, robj *key, expireEntry &&e)
|
||||
* is associated with this key (i.e. the key is non volatile) */
|
||||
expireEntry *redisDbPersistentDataSnapshot::getExpire(const char *key) {
|
||||
/* No expire? return ASAP */
|
||||
std::unique_lock<fastlock> ul(g_expireLock);
|
||||
if (expireSize() == 0)
|
||||
return nullptr;
|
||||
|
||||
@@ -2608,15 +2607,12 @@ void clusterStorageLoadCallback(const char *rgchkey, size_t cch, void *)
|
||||
slotToKeyUpdateKeyCore(rgchkey, cch, true /*add*/);
|
||||
}
|
||||
|
||||
void moduleLoadCallback(const char * rgchKey, size_t, void *data) {
|
||||
redisObjectStack keyobj;
|
||||
initStaticStringObject(keyobj, const_cast<char *>(rgchKey));
|
||||
moduleNotifyKeyspaceEvent(NOTIFY_LOADED, "loaded", &keyobj, *(int *)data);
|
||||
}
|
||||
|
||||
void moduleClusterLoadCallback(const char * rgchKey, size_t cchKey, void *data) {
|
||||
clusterStorageLoadCallback(rgchKey, cchKey, data);
|
||||
moduleLoadCallback(rgchKey, cchKey, data);
|
||||
void moduleLoadCallback(const char * rgchKey, size_t cchKey, void *data) {
|
||||
if (g_pserver->cluster_enabled) {
|
||||
clusterStorageLoadCallback(rgchKey, cchKey, data);
|
||||
}
|
||||
robj *keyobj = createEmbeddedStringObject(rgchKey, cchKey);
|
||||
moduleNotifyKeyspaceEvent(NOTIFY_LOADED, "loaded", keyobj, *(int *)data);
|
||||
}
|
||||
|
||||
void redisDb::initialize(int id)
|
||||
@@ -2637,7 +2633,7 @@ void redisDb::storageProviderInitialize()
|
||||
{
|
||||
if (g_pserver->m_pstorageFactory != nullptr)
|
||||
{
|
||||
IStorageFactory::key_load_iterator itr = g_pserver->cluster_enabled ? moduleClusterLoadCallback : moduleLoadCallback;
|
||||
IStorageFactory::key_load_iterator itr = moduleLoadCallback;
|
||||
this->setStorageProvider(StorageCache::create(g_pserver->m_pstorageFactory, id, itr, &id));
|
||||
}
|
||||
}
|
||||
@@ -2728,11 +2724,8 @@ void redisDbPersistentData::clear(void(callback)(void*))
|
||||
m_cnewKeysPending = 0;
|
||||
m_fAllChanged++;
|
||||
}
|
||||
{
|
||||
std::unique_lock<fastlock> ul(g_expireLock);
|
||||
delete m_setexpire;
|
||||
m_setexpire = new (MALLOC_LOCAL) expireset();
|
||||
}
|
||||
if (m_spstorage != nullptr)
|
||||
m_spstorage->clear(callback);
|
||||
dictEmpty(m_pdictTombstone,callback);
|
||||
@@ -2865,8 +2858,7 @@ LNotFound:
|
||||
{
|
||||
dictAdd(m_pdict, sdsNewKey, o);
|
||||
o->SetFExpires(spexpire != nullptr);
|
||||
|
||||
std::unique_lock<fastlock> ul(g_expireLock);
|
||||
|
||||
if (spexpire != nullptr)
|
||||
{
|
||||
auto itr = m_setexpire->find(sdsKey);
|
||||
@@ -2889,7 +2881,6 @@ LNotFound:
|
||||
if (*pde != nullptr && dictGetVal(*pde) != nullptr)
|
||||
{
|
||||
robj *o = (robj*)dictGetVal(*pde);
|
||||
std::unique_lock<fastlock> ul(g_expireLock);
|
||||
serverAssert(o->FExpires() == (m_setexpire->find(sdsKey) != m_setexpire->end()));
|
||||
}
|
||||
}
|
||||
@@ -3011,16 +3002,8 @@ void redisDbPersistentData::processChangesAsync(std::atomic<int> &pendingJobs)
|
||||
});
|
||||
}
|
||||
|
||||
/* This function is to bulk insert directly to storage provider bypassing in memory, assumes rgKeys and rgVals are not sds strings */
|
||||
void redisDbPersistentData::bulkDirectStorageInsert(char **rgKeys, size_t *rgcbKeys, char **rgVals, size_t *rgcbVals, size_t celem)
|
||||
void redisDbPersistentData::bulkStorageInsert(char **rgKeys, size_t *rgcbKeys, char **rgVals, size_t *rgcbVals, size_t celem)
|
||||
{
|
||||
if (g_pserver->cluster_enabled) {
|
||||
aeAcquireLock();
|
||||
for (size_t i = 0; i < celem; i++) {
|
||||
slotToKeyUpdateKeyCore(rgKeys[i], rgcbKeys[i], 1);
|
||||
}
|
||||
aeReleaseLock();
|
||||
}
|
||||
m_spstorage->bulkInsert(rgKeys, rgcbKeys, rgVals, rgcbVals, celem);
|
||||
}
|
||||
|
||||
@@ -3262,7 +3245,6 @@ std::unique_ptr<expireEntry> deserializeExpire(sds key, const char *str, size_t
|
||||
|
||||
sds serializeStoredObjectAndExpire(redisDbPersistentData *db, const char *key, robj_roptr o)
|
||||
{
|
||||
std::unique_lock<fastlock> ul(g_expireLock);
|
||||
auto itrExpire = db->setexpire()->find(key);
|
||||
const expireEntry *pexpire = nullptr;
|
||||
if (itrExpire != db->setexpire()->end())
|
||||
@@ -3387,7 +3369,6 @@ void redisDbPersistentData::prefetchKeysAsync(client *c, parsed_command &command
|
||||
dictAdd(m_pdict, sharedKey, o);
|
||||
o->SetFExpires(spexpire != nullptr);
|
||||
|
||||
std::unique_lock<fastlock> ul(g_expireLock);
|
||||
if (spexpire != nullptr)
|
||||
{
|
||||
auto itr = m_setexpire->find(sharedKey);
|
||||
|
||||
+4
-4
@@ -341,10 +341,10 @@ void mallctl_int(client *c, robj **argv, int argc) {
|
||||
}
|
||||
size_t sz = sizeof(old);
|
||||
while (sz > 0) {
|
||||
if ((ret=mallctl(szFromObj(argv[0]), &old, &sz, argc > 1? &val: NULL, argc > 1?sz: 0))) {
|
||||
if ((ret=je_mallctl(szFromObj(argv[0]), &old, &sz, argc > 1? &val: NULL, argc > 1?sz: 0))) {
|
||||
if (ret == EPERM && argc > 1) {
|
||||
/* if this option is write only, try just writing to it. */
|
||||
if (!(ret=mallctl(szFromObj(argv[0]), NULL, 0, &val, sz))) {
|
||||
if (!(ret=je_mallctl(szFromObj(argv[0]), NULL, 0, &val, sz))) {
|
||||
addReply(c, shared.ok);
|
||||
return;
|
||||
}
|
||||
@@ -375,7 +375,7 @@ void mallctl_string(client *c, robj **argv, int argc) {
|
||||
char *old;
|
||||
size_t sz = sizeof(old);
|
||||
/* for strings, it seems we need to first get the old value, before overriding it. */
|
||||
if ((rret=mallctl(szFromObj(argv[0]), &old, &sz, NULL, 0))) {
|
||||
if ((rret=je_mallctl(szFromObj(argv[0]), &old, &sz, NULL, 0))) {
|
||||
/* return error unless this option is write only. */
|
||||
if (!(rret == EPERM && argc > 1)) {
|
||||
addReplyErrorFormat(c,"%s", strerror(rret));
|
||||
@@ -387,7 +387,7 @@ void mallctl_string(client *c, robj **argv, int argc) {
|
||||
char **valref = &val;
|
||||
if ((!strcmp(val,"VOID")))
|
||||
valref = NULL, sz = 0;
|
||||
wret = mallctl(szFromObj(argv[0]), NULL, 0, valref, sz);
|
||||
wret = je_mallctl(szFromObj(argv[0]), NULL, 0, valref, sz);
|
||||
}
|
||||
if (!rret)
|
||||
addReplyBulkCString(c, old);
|
||||
|
||||
+1
-2
@@ -380,7 +380,7 @@ size_t freeMemoryGetNotCountedMemory(void) {
|
||||
|
||||
/* also don't count the replication backlog memory
|
||||
* that's where the replication clients get their memory from */
|
||||
overhead += g_pserver->repl_backlog_size - g_pserver->repl_backlog_config_size;
|
||||
overhead += g_pserver->repl_backlog_size;
|
||||
|
||||
if (g_pserver->aof_state != AOF_OFF) {
|
||||
overhead += sdsalloc(g_pserver->aof_buf)+aofRewriteBufferSize();
|
||||
@@ -771,7 +771,6 @@ int performEvictions(bool fPreSnapshot) {
|
||||
if (db->removeCachedValue(bestkey, &deT)) {
|
||||
mem_freed += splazy->addEntry(db->dictUnsafeKeyOnly(), deT);
|
||||
ckeysFailed = 0;
|
||||
g_pserver->stat_evictedkeys++;
|
||||
}
|
||||
else {
|
||||
delta = 0;
|
||||
|
||||
@@ -481,7 +481,6 @@ void expireSlaveKeys(void) {
|
||||
if (slaveKeysWithExpire == NULL ||
|
||||
dictSize(slaveKeysWithExpire) == 0) return;
|
||||
|
||||
std::unique_lock<fastlock> ul(g_expireLock);
|
||||
int cycles = 0, noexpire = 0;
|
||||
mstime_t start = mstime();
|
||||
while(1) {
|
||||
|
||||
@@ -41,3 +41,10 @@ void operator delete(void *p, std::size_t) noexcept
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(USE_JEMALLOC)
|
||||
extern "C" size_t malloc_usable_size(void *ptr)
|
||||
{
|
||||
return zmalloc_usable_size(ptr);
|
||||
}
|
||||
#endif
|
||||
+1
-2
@@ -1541,7 +1541,7 @@ void memoryCommand(client *c) {
|
||||
} else if (!strcasecmp(szFromObj(c->argv[1]),"malloc-stats") && c->argc == 2) {
|
||||
#if defined(USE_JEMALLOC)
|
||||
sds info = sdsempty();
|
||||
malloc_stats_print(inputCatSds, &info, NULL);
|
||||
je_malloc_stats_print(inputCatSds, &info, NULL);
|
||||
addReplyVerbatim(c,info,sdslen(info),"txt");
|
||||
sdsfree(info);
|
||||
#else
|
||||
@@ -1668,7 +1668,6 @@ robj *deserializeStoredObjectCore(const void *data, size_t cb)
|
||||
robj *deserializeStoredObject(const redisDbPersistentData *db, const char *key, const void *data, size_t cb)
|
||||
{
|
||||
robj *o = deserializeStoredObjectCore(data, cb);
|
||||
std::unique_lock<fastlock> ul(g_expireLock);
|
||||
o->SetFExpires(db->setexpire()->exists(key));
|
||||
return o;
|
||||
}
|
||||
|
||||
+50
-123
@@ -1334,7 +1334,7 @@ int rdbSaveRio(rio *rdb, const redisDbPersistentDataSnapshot **rgpdb, int *error
|
||||
if (rdbSaveModulesAux(rdb, REDISMODULE_AUX_BEFORE_RDB) == -1) goto werr;
|
||||
|
||||
for (j = 0; j < cserver.dbnum; j++) {
|
||||
const redisDbPersistentDataSnapshot *db = rgpdb != nullptr ? rgpdb[j] : g_pserver->db[j];
|
||||
const redisDbPersistentDataSnapshot *db = rgpdb[j];
|
||||
if (db->size() == 0) continue;
|
||||
|
||||
/* Write the SELECT DB opcode */
|
||||
@@ -1490,7 +1490,7 @@ int rdbSaveFile(char *filename, const redisDbPersistentDataSnapshot **rgpdb, rdb
|
||||
rio rdb;
|
||||
int error = 0;
|
||||
|
||||
getTempFileName(tmpfile, g_pserver->rdbThreadVars.tmpfileNum);
|
||||
snprintf(tmpfile,sizeof(tmpfile),"temp-%d-%d.rdb", getpid(), g_pserver->rdbThreadVars.tmpfileNum);
|
||||
fp = fopen(tmpfile,"w");
|
||||
if (!fp) {
|
||||
char *cwdp = getcwd(cwd,MAXPATHLEN);
|
||||
@@ -1660,14 +1660,12 @@ int launchRdbSaveThread(pthread_t &child, rdbSaveInfo *rsi)
|
||||
pthread_attr_t tattr;
|
||||
pthread_attr_init(&tattr);
|
||||
pthread_attr_setstacksize(&tattr, 1 << 23); // 8 MB
|
||||
openChildInfoPipe();
|
||||
if (pthread_create(&child, &tattr, rdbSaveThread, args)) {
|
||||
pthread_attr_destroy(&tattr);
|
||||
for (int idb = 0; idb < cserver.dbnum; ++idb)
|
||||
g_pserver->db[idb]->endSnapshot(args->rgpdb[idb]);
|
||||
args->~rdbSaveThreadArgs();
|
||||
zfree(args);
|
||||
closeChildInfoPipe();
|
||||
return C_ERR;
|
||||
}
|
||||
pthread_attr_destroy(&tattr);
|
||||
@@ -1685,11 +1683,13 @@ int rdbSaveBackground(rdbSaveInfo *rsi) {
|
||||
|
||||
g_pserver->dirty_before_bgsave = g_pserver->dirty;
|
||||
g_pserver->lastbgsave_try = time(NULL);
|
||||
openChildInfoPipe();
|
||||
|
||||
start = ustime();
|
||||
latencyStartMonitor(g_pserver->rdb_save_latency);
|
||||
|
||||
if (launchRdbSaveThread(child, rsi) != C_OK) {
|
||||
closeChildInfoPipe();
|
||||
g_pserver->lastbgsave_status = C_ERR;
|
||||
serverLog(LL_WARNING,"Can't save in background: fork: %s",
|
||||
strerror(errno));
|
||||
@@ -1715,7 +1715,7 @@ void getTempFileName(char tmpfile[], int tmpfileNum) {
|
||||
char tmpfileNumString[214];
|
||||
|
||||
/* Generate temp rdb file name using aync-signal safe functions. */
|
||||
int pid_len = ll2string(pid, sizeof(pid), g_pserver->in_fork_child ? getppid() : getpid());
|
||||
int pid_len = ll2string(pid, sizeof(pid), getpid());
|
||||
int tmpfileNum_len = ll2string(tmpfileNumString, sizeof(tmpfileNumString), tmpfileNum);
|
||||
strcpy(tmpfile, "temp-");
|
||||
strncpy(tmpfile+5, pid, pid_len);
|
||||
@@ -3832,130 +3832,57 @@ int rdbSaveToSlavesSockets(rdbSaveInfo *rsi) {
|
||||
}
|
||||
|
||||
/* Create the child process. */
|
||||
if (cserver.fForkBgSave) {
|
||||
pid_t childpid;
|
||||
if ((childpid = redisFork(CHILD_TYPE_RDB)) == 0) {
|
||||
/* Child */
|
||||
int retval, dummy;
|
||||
rio rdb;
|
||||
openChildInfoPipe();
|
||||
|
||||
rioInitWithFd(&rdb,args->rdb_pipe_write);
|
||||
for (int idb = 0; idb < cserver.dbnum; ++idb)
|
||||
args->rgpdb[idb] = g_pserver->db[idb]->createSnapshot(getMvccTstamp(), false /*fOptional*/);
|
||||
|
||||
redisSetProcTitle("keydb-rdb-to-slaves");
|
||||
redisSetCpuAffinity(g_pserver->bgsave_cpulist);
|
||||
|
||||
retval = rdbSaveRioWithEOFMark(&rdb,nullptr,nullptr,rsi);
|
||||
if (retval == C_OK && rioFlush(&rdb) == 0)
|
||||
retval = C_ERR;
|
||||
|
||||
if (retval == C_OK) {
|
||||
sendChildCowInfo(CHILD_INFO_TYPE_RDB_COW_SIZE, "RDB");
|
||||
}
|
||||
|
||||
rioFreeFd(&rdb);
|
||||
/* wake up the reader, tell it we're done. */
|
||||
close(args->rdb_pipe_write);
|
||||
close(g_pserver->rdb_child_exit_pipe); /* close write end so that we can detect the close on the parent. */
|
||||
/* hold exit until the parent tells us it's safe. we're not expecting
|
||||
* to read anything, just get the error when the pipe is closed. */
|
||||
dummy = read(args->safe_to_exit_pipe, pipefds, 1);
|
||||
UNUSED(dummy);
|
||||
exitFromChild((retval == C_OK) ? 0 : 1);
|
||||
} else {
|
||||
/* Parent */
|
||||
close(args->safe_to_exit_pipe);
|
||||
if (childpid == -1) {
|
||||
serverLog(LL_WARNING,"Can't save in background: fork: %s",
|
||||
strerror(errno));
|
||||
|
||||
/* Undo the state change. The caller will perform cleanup on
|
||||
* all the slaves in BGSAVE_START state, but an early call to
|
||||
* replicationSetupSlaveForFullResync() turned it into BGSAVE_END */
|
||||
listRewind(g_pserver->slaves,&li);
|
||||
while((ln = listNext(&li))) {
|
||||
client *replica = (client*)ln->value;
|
||||
if (replica->replstate == SLAVE_STATE_WAIT_BGSAVE_END) {
|
||||
replica->replstate = SLAVE_STATE_WAIT_BGSAVE_START;
|
||||
}
|
||||
}
|
||||
close(args->rdb_pipe_write);
|
||||
close(g_pserver->rdb_pipe_read);
|
||||
zfree(g_pserver->rdb_pipe_conns);
|
||||
g_pserver->rdb_pipe_conns = NULL;
|
||||
g_pserver->rdb_pipe_numconns = 0;
|
||||
g_pserver->rdb_pipe_numconns_writing = 0;
|
||||
args->rsi.~rdbSaveInfo();
|
||||
zfree(args);
|
||||
} else {
|
||||
serverLog(LL_NOTICE,"Background RDB transfer started by pid %ld",
|
||||
(long)childpid);
|
||||
g_pserver->rdb_save_time_start = time(NULL);
|
||||
g_pserver->rdb_child_type = RDB_CHILD_TYPE_SOCKET;
|
||||
g_pserver->rdbThreadVars.fRdbThreadActive = true;
|
||||
updateDictResizePolicy();
|
||||
close(args->rdb_pipe_write); /* close write in parent so that it can detect the close on the child. */
|
||||
aePostFunction(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el, []{
|
||||
if (aeCreateFileEvent(serverTL->el, g_pserver->rdb_pipe_read, AE_READABLE, rdbPipeReadHandler, nullptr) == AE_ERR) {
|
||||
serverPanic("Unrecoverable error creating g_pserver->rdb_pipe_read file event.");
|
||||
}
|
||||
});
|
||||
}
|
||||
return (childpid == -1) ? C_ERR : C_OK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
openChildInfoPipe();
|
||||
|
||||
for (int idb = 0; idb < cserver.dbnum; ++idb)
|
||||
args->rgpdb[idb] = g_pserver->db[idb]->createSnapshot(getMvccTstamp(), false /*fOptional*/);
|
||||
|
||||
g_pserver->rdbThreadVars.tmpfileNum++;
|
||||
g_pserver->rdbThreadVars.fRdbThreadCancel = false;
|
||||
pthread_attr_t tattr;
|
||||
pthread_attr_init(&tattr);
|
||||
pthread_attr_setstacksize(&tattr, 1 << 23); // 8 MB
|
||||
if (pthread_create(&child, &tattr, rdbSaveToSlavesSocketsThread, args)) {
|
||||
pthread_attr_destroy(&tattr);
|
||||
serverLog(LL_WARNING,"Can't save in background: fork: %s",
|
||||
strerror(errno));
|
||||
|
||||
/* Undo the state change. The caller will perform cleanup on
|
||||
* all the slaves in BGSAVE_START state, but an early call to
|
||||
* replicationSetupSlaveForFullResync() turned it into BGSAVE_END */
|
||||
listRewind(g_pserver->slaves,&li);
|
||||
while((ln = listNext(&li))) {
|
||||
client *replica = (client*)ln->value;
|
||||
if (replica->replstate == SLAVE_STATE_WAIT_BGSAVE_END) {
|
||||
replica->replstate = SLAVE_STATE_WAIT_BGSAVE_START;
|
||||
}
|
||||
}
|
||||
close(args->rdb_pipe_write);
|
||||
close(g_pserver->rdb_pipe_read);
|
||||
zfree(g_pserver->rdb_pipe_conns);
|
||||
close(args->safe_to_exit_pipe);
|
||||
g_pserver->rdb_pipe_conns = NULL;
|
||||
g_pserver->rdb_pipe_numconns = 0;
|
||||
g_pserver->rdb_pipe_numconns_writing = 0;
|
||||
args->rsi.~rdbSaveInfo();
|
||||
zfree(args);
|
||||
closeChildInfoPipe();
|
||||
return C_ERR;
|
||||
}
|
||||
g_pserver->rdbThreadVars.tmpfileNum++;
|
||||
g_pserver->rdbThreadVars.fRdbThreadCancel = false;
|
||||
pthread_attr_t tattr;
|
||||
pthread_attr_init(&tattr);
|
||||
pthread_attr_setstacksize(&tattr, 1 << 23); // 8 MB
|
||||
if (pthread_create(&child, &tattr, rdbSaveToSlavesSocketsThread, args)) {
|
||||
pthread_attr_destroy(&tattr);
|
||||
g_pserver->child_type = CHILD_TYPE_RDB;
|
||||
serverLog(LL_WARNING,"Can't save in background: fork: %s",
|
||||
strerror(errno));
|
||||
|
||||
serverLog(LL_NOTICE,"Background RDB transfer started");
|
||||
g_pserver->rdb_save_time_start = time(NULL);
|
||||
serverAssert(!g_pserver->rdbThreadVars.fRdbThreadActive);
|
||||
g_pserver->rdbThreadVars.rdb_child_thread = child;
|
||||
g_pserver->rdbThreadVars.fRdbThreadActive = true;
|
||||
g_pserver->rdb_child_type = RDB_CHILD_TYPE_SOCKET;
|
||||
aePostFunction(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el, []{
|
||||
if (aeCreateFileEvent(serverTL->el, g_pserver->rdb_pipe_read, AE_READABLE, rdbPipeReadHandler, nullptr) == AE_ERR) {
|
||||
serverPanic("Unrecoverable error creating server.rdb_pipe_read file event.");
|
||||
/* Undo the state change. The caller will perform cleanup on
|
||||
* all the slaves in BGSAVE_START state, but an early call to
|
||||
* replicationSetupSlaveForFullResync() turned it into BGSAVE_END */
|
||||
listRewind(g_pserver->slaves,&li);
|
||||
while((ln = listNext(&li))) {
|
||||
client *replica = (client*)ln->value;
|
||||
if (replica->replstate == SLAVE_STATE_WAIT_BGSAVE_END) {
|
||||
replica->replstate = SLAVE_STATE_WAIT_BGSAVE_START;
|
||||
}
|
||||
});
|
||||
}
|
||||
close(args->rdb_pipe_write);
|
||||
close(g_pserver->rdb_pipe_read);
|
||||
zfree(g_pserver->rdb_pipe_conns);
|
||||
close(args->safe_to_exit_pipe);
|
||||
g_pserver->rdb_pipe_conns = NULL;
|
||||
g_pserver->rdb_pipe_numconns = 0;
|
||||
g_pserver->rdb_pipe_numconns_writing = 0;
|
||||
args->rsi.~rdbSaveInfo();
|
||||
zfree(args);
|
||||
closeChildInfoPipe();
|
||||
return C_ERR;
|
||||
}
|
||||
pthread_attr_destroy(&tattr);
|
||||
g_pserver->child_type = CHILD_TYPE_RDB;
|
||||
|
||||
serverLog(LL_NOTICE,"Background RDB transfer started");
|
||||
g_pserver->rdb_save_time_start = time(NULL);
|
||||
serverAssert(!g_pserver->rdbThreadVars.fRdbThreadActive);
|
||||
g_pserver->rdbThreadVars.rdb_child_thread = child;
|
||||
g_pserver->rdbThreadVars.fRdbThreadActive = true;
|
||||
g_pserver->rdb_child_type = RDB_CHILD_TYPE_SOCKET;
|
||||
aePostFunction(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el, []{
|
||||
if (aeCreateFileEvent(serverTL->el, g_pserver->rdb_pipe_read, AE_READABLE, rdbPipeReadHandler,NULL) == AE_ERR) {
|
||||
serverPanic("Unrecoverable error creating server.rdb_pipe_read file event.");
|
||||
}
|
||||
});
|
||||
|
||||
return C_OK; /* Unreached. */
|
||||
}
|
||||
|
||||
@@ -151,7 +151,6 @@ int rdbLoad(rdbSaveInfo *rsi, int rdbflags);
|
||||
int rdbLoadFile(const char *filename, rdbSaveInfo *rsi, int rdbflags);
|
||||
int rdbSaveBackground(rdbSaveInfo *rsi);
|
||||
int rdbSaveToSlavesSockets(rdbSaveInfo *rsi);
|
||||
void getTempFileName(char tmpfile[], int tmpfileNum);
|
||||
void rdbRemoveTempFile(pid_t childpid, int from_signal);
|
||||
int rdbSave(const redisDbPersistentDataSnapshot **rgpdb, rdbSaveInfo *rsi);
|
||||
int rdbSaveFile(char *filename, const redisDbPersistentDataSnapshot **rgpdb, rdbSaveInfo *rsi);
|
||||
|
||||
+3
-5
@@ -3797,11 +3797,9 @@ int connectWithMaster(redisMaster *mi) {
|
||||
connSetPrivateData(mi->repl_transfer_s, mi);
|
||||
if (connConnect(mi->repl_transfer_s, mi->masterhost, mi->masterport,
|
||||
NET_FIRST_BIND_ADDR, syncWithMaster) == C_ERR) {
|
||||
const char *err = "Unknown Error";
|
||||
if (mi->repl_transfer_s->last_errno != 0)
|
||||
err = connGetLastError(mi->repl_transfer_s);
|
||||
int sev = g_pserver->enable_multimaster ? LL_NOTICE : LL_WARNING; // with multimaster its not unheard of to intentionally have downed masters
|
||||
serverLog(sev, "Unable to connect to MASTER: %s", err);
|
||||
int sev = g_pserver->enable_multimaster ? LL_NOTICE : LL_WARNING; // with multimaster its not unheard of to intentiallionall have downed masters
|
||||
serverLog(sev,"Unable to connect to MASTER: %s",
|
||||
connGetLastError(mi->repl_transfer_s));
|
||||
connClose(mi->repl_transfer_s);
|
||||
mi->repl_transfer_s = NULL;
|
||||
return C_ERR;
|
||||
|
||||
@@ -1264,9 +1264,6 @@ void scriptingInit(int setup) {
|
||||
|
||||
/* Finally set the table as 'redis' global var. */
|
||||
lua_setglobal(lua,"redis");
|
||||
/* Set table as 'keydb' global var as well */
|
||||
lua_getglobal(lua,"redis");
|
||||
lua_setglobal(lua,"keydb");
|
||||
|
||||
/* Replace math.random and math.randomseed with our implementations. */
|
||||
lua_getglobal(lua,"math");
|
||||
|
||||
+1
-2
@@ -2219,7 +2219,6 @@ void checkChildrenDone(void) {
|
||||
g_pserver->rdbThreadVars.fRdbThreadCancel = false;
|
||||
g_pserver->rdbThreadVars.fDone = false;
|
||||
if (exitcode == 0) receiveChildInfo();
|
||||
closeChildInfoPipe();
|
||||
}
|
||||
}
|
||||
else if ((pid = waitpid(-1, &statloc, WNOHANG)) != 0) {
|
||||
@@ -5172,7 +5171,7 @@ int prepareForShutdown(int flags) {
|
||||
* to unlink file actully) in background thread.
|
||||
* The temp rdb file fd may won't be closed when redis exits quickly,
|
||||
* but OS will close this fd when process exits. */
|
||||
rdbRemoveTempFile(g_pserver->rdbThreadVars.tmpfileNum, 0);
|
||||
rdbRemoveTempFile(g_pserver->child_pid, 0);
|
||||
}
|
||||
|
||||
/* Kill module child if there is one. */
|
||||
|
||||
+6
-6
@@ -1209,7 +1209,7 @@ public:
|
||||
bool FSnapshot() const { return m_spdbSnapshotHOLDER != nullptr; }
|
||||
|
||||
std::unique_ptr<const StorageCache> CloneStorageCache() { return std::unique_ptr<const StorageCache>(m_spstorage->clone()); }
|
||||
void bulkDirectStorageInsert(char **rgKeys, size_t *rgcbKeys, char **rgVals, size_t *rgcbVals, size_t celem);
|
||||
void bulkStorageInsert(char **rgKeys, size_t *rgcbKeys, char **rgVals, size_t *rgcbVals, size_t celem);
|
||||
|
||||
dict_iter find_cached_threadsafe(const char *key) const;
|
||||
|
||||
@@ -1370,7 +1370,7 @@ struct redisDb : public redisDbPersistentDataSnapshot
|
||||
using redisDbPersistentData::FRehashing;
|
||||
using redisDbPersistentData::FTrackingChanges;
|
||||
using redisDbPersistentData::CloneStorageCache;
|
||||
using redisDbPersistentData::bulkDirectStorageInsert;
|
||||
using redisDbPersistentData::bulkStorageInsert;
|
||||
|
||||
public:
|
||||
const redisDbPersistentDataSnapshot *createSnapshot(uint64_t mvccCheckpoint, bool fOptional) {
|
||||
@@ -3894,13 +3894,13 @@ void incrementMvccTstamp();
|
||||
|
||||
#if __GNUC__ >= 7 && !defined(NO_DEPRECATE_FREE)
|
||||
[[deprecated]]
|
||||
void *calloc(size_t count, size_t size) noexcept;
|
||||
void *calloc(size_t count, size_t size);
|
||||
[[deprecated]]
|
||||
void free(void *ptr) noexcept;
|
||||
void free(void *ptr);
|
||||
[[deprecated]]
|
||||
void *malloc(size_t size) noexcept;
|
||||
void *malloc(size_t size);
|
||||
[[deprecated]]
|
||||
void *realloc(void *ptr, size_t size) noexcept;
|
||||
void *realloc(void *ptr, size_t size);
|
||||
#endif
|
||||
|
||||
/* Debugging stuff */
|
||||
|
||||
+13
-13
@@ -80,12 +80,12 @@ static_assert((PREFIX_SIZE % 16) == 0, "Our prefix must be modulo 16-bytes or ou
|
||||
#define realloc(ptr,size, type) tc_realloc(ptr,size)
|
||||
#define free(ptr) tc_free(ptr)
|
||||
#elif defined(USE_JEMALLOC)
|
||||
#define malloc(size, type) malloc(size)
|
||||
#define calloc(count,size,type) calloc(count,size)
|
||||
#define realloc(ptr,size,type) realloc(ptr,size)
|
||||
#define free(ptr) free(ptr)
|
||||
#define mallocx(size,flags) mallocx(size,flags)
|
||||
#define dallocx(ptr,flags) dallocx(ptr,flags)
|
||||
#define malloc(size, type) je_malloc(size)
|
||||
#define calloc(count,size,type) je_calloc(count,size)
|
||||
#define realloc(ptr,size,type) je_realloc(ptr,size)
|
||||
#define free(ptr) je_free(ptr)
|
||||
#define mallocx(size,flags) je_mallocx(size,flags)
|
||||
#define dallocx(ptr,flags) je_dallocx(ptr,flags)
|
||||
#else
|
||||
#define malloc(size, type) malloc(size)
|
||||
#define calloc(count,size,type) calloc(count,size)
|
||||
@@ -494,17 +494,17 @@ int zmalloc_get_allocator_info(size_t *allocated,
|
||||
*allocated = *resident = *active = 0;
|
||||
/* Update the statistics cached by mallctl. */
|
||||
sz = sizeof(epoch);
|
||||
mallctl("epoch", &epoch, &sz, &epoch, sz);
|
||||
je_mallctl("epoch", &epoch, &sz, &epoch, sz);
|
||||
sz = sizeof(size_t);
|
||||
/* Unlike RSS, this does not include RSS from shared libraries and other non
|
||||
* heap mappings. */
|
||||
mallctl("stats.resident", resident, &sz, NULL, 0);
|
||||
je_mallctl("stats.resident", resident, &sz, NULL, 0);
|
||||
/* Unlike resident, this doesn't not include the pages jemalloc reserves
|
||||
* for re-use (purge will clean that). */
|
||||
mallctl("stats.active", active, &sz, NULL, 0);
|
||||
je_mallctl("stats.active", active, &sz, NULL, 0);
|
||||
/* Unlike zmalloc_used_memory, this matches the stats.resident by taking
|
||||
* into account all allocations done by this process (not only zmalloc). */
|
||||
mallctl("stats.allocated", allocated, &sz, NULL, 0);
|
||||
je_mallctl("stats.allocated", allocated, &sz, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -512,7 +512,7 @@ void set_jemalloc_bg_thread(int enable) {
|
||||
/* let jemalloc do purging asynchronously, required when there's no traffic
|
||||
* after flushdb */
|
||||
char val = !!enable;
|
||||
mallctl("background_thread", NULL, 0, &val, 1);
|
||||
je_mallctl("background_thread", NULL, 0, &val, 1);
|
||||
}
|
||||
|
||||
int jemalloc_purge() {
|
||||
@@ -520,9 +520,9 @@ int jemalloc_purge() {
|
||||
char tmp[32];
|
||||
unsigned narenas = 0;
|
||||
size_t sz = sizeof(unsigned);
|
||||
if (!mallctl("arenas.narenas", &narenas, &sz, NULL, 0)) {
|
||||
if (!je_mallctl("arenas.narenas", &narenas, &sz, NULL, 0)) {
|
||||
snprintf(tmp, sizeof(tmp), "arena.%d.purge", narenas);
|
||||
if (!mallctl(tmp, NULL, 0, NULL, 0))
|
||||
if (!je_mallctl(tmp, NULL, 0, NULL, 0))
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@
|
||||
#include <jemalloc/jemalloc.h>
|
||||
#if (JEMALLOC_VERSION_MAJOR == 2 && JEMALLOC_VERSION_MINOR >= 1) || (JEMALLOC_VERSION_MAJOR > 2)
|
||||
#define HAVE_MALLOC_SIZE 1
|
||||
#define zmalloc_size(p) malloc_usable_size(p)
|
||||
#define zmalloc_size(p) je_malloc_usable_size(p)
|
||||
#else
|
||||
#error "Newer version of jemalloc required"
|
||||
#endif
|
||||
|
||||
@@ -162,16 +162,15 @@ start_server {tags {"introspection"}} {
|
||||
aof_rewrite_cpulist
|
||||
time-thread-priority
|
||||
bgsave_cpulist
|
||||
storage-cache-mode
|
||||
storage-provider-options
|
||||
use-fork
|
||||
storage-cache-mode
|
||||
storage-provider-options
|
||||
use-fork
|
||||
multi-master
|
||||
active-replica
|
||||
bind
|
||||
set-proc-title
|
||||
repl-backlog-disk-reserve
|
||||
tls-allowlist
|
||||
db-s3-object
|
||||
}
|
||||
|
||||
if {!$::tls} {
|
||||
|
||||
@@ -43,15 +43,10 @@ start_server {tags {"scripting"}} {
|
||||
r eval {return redis.call('get',KEYS[1])} 1 mykey
|
||||
} {myval}
|
||||
|
||||
test {EVAL - keys command works? } {
|
||||
test { EVAL - keys command works? } {
|
||||
r eval {return redis.call('keys', 'test')} 0
|
||||
}
|
||||
|
||||
test {EVAL - KeyDB global works } {
|
||||
r eval {return keydb.call('get', KEYS[1])} 1 mykey
|
||||
assert_equal [r eval {return redis.call('get',KEYS[1])} 1 mykey] [r eval {return keydb.call('get', KEYS[1])} 1 mykey]
|
||||
}
|
||||
|
||||
test {EVALSHA - Can we call a SHA1 if already defined?} {
|
||||
r evalsha fd758d1589d044dd850a6f05d52f2eefd27f033f 1 mykey
|
||||
} {myval}
|
||||
|
||||
@@ -26,11 +26,7 @@ then
|
||||
while [ $((PORT < ENDPORT)) != "0" ]; do
|
||||
PORT=$((PORT+1))
|
||||
echo "Starting $PORT"
|
||||
if [ "$2" == "flash" ]
|
||||
then
|
||||
ADDITIONAL_OPTIONS="--save \"\" \"\" \"\" --semi-ordered-set-bucket-size 8 --client-output-buffer-limit replica 1 1 0 --maxmemory 100000000 --storage-provider flash ./$PORT.flash"
|
||||
fi
|
||||
$BIN_PATH/keydb-server --server-threads 4 --port $PORT --protected-mode $PROTECTED_MODE --cluster-enabled yes --cluster-config-file nodes-${PORT}.conf --cluster-node-timeout $TIMEOUT --dbfilename dump-${PORT}.rdb --logfile ${PORT}.log --daemonize yes ${ADDITIONAL_OPTIONS}
|
||||
$BIN_PATH/keydb-server --port $PORT --protected-mode $PROTECTED_MODE --cluster-enabled yes --cluster-config-file nodes-${PORT}.conf --cluster-node-timeout $TIMEOUT --appendonly yes --appendfilename appendonly-${PORT}.aof --dbfilename dump-${PORT}.rdb --logfile ${PORT}.log --daemonize yes ${ADDITIONAL_OPTIONS}
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
@@ -101,8 +97,6 @@ then
|
||||
rm -rf appendonly*.aof
|
||||
rm -rf dump*.rdb
|
||||
rm -rf nodes*.conf
|
||||
rm -rf *.flash
|
||||
rm -rf temp*.rdb
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
Reference in new issue
Block a user