Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07cb1f4581 | ||
|
|
f2ca2aa1f7 | ||
|
|
b20bf10fda | ||
|
|
fa6870a268 | ||
|
|
c3d3c82f3a | ||
|
|
f534b5b3a2 | ||
|
|
27da034819 | ||
|
|
6ec1641294 | ||
|
|
7b79ec360b | ||
|
|
56fc6b7deb | ||
|
|
528a43bd6c | ||
|
|
b357803362 | ||
|
|
448808529a | ||
|
|
a0bc208412 | ||
|
|
6b0172b9bf | ||
|
|
bc1eccb66d | ||
|
|
a9249d4a82 | ||
|
|
3c373494d6 | ||
|
|
5aef606d3b | ||
|
|
2ec0b2cd20 | ||
|
|
cd76a71de3 | ||
|
|
c2a98a60f9 |
No files matched your search
+8
-4
@@ -82,6 +82,10 @@ ifneq (,$(findstring armv,$(uname_M)))
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring armv,$(uname_M)))
|
||||
FINAL_LIBS+=-latomic
|
||||
endif
|
||||
|
||||
# Backwards compatibility for selecting an allocator
|
||||
ifeq ($(USE_TCMALLOC),yes)
|
||||
MALLOC=tcmalloc
|
||||
@@ -105,7 +109,7 @@ endif
|
||||
FINAL_CFLAGS=$(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS) $(REDIS_CFLAGS)
|
||||
FINAL_CXXFLAGS=$(CXX_STD) $(WARN) $(OPT) $(DEBUG) $(CXXFLAGS) $(REDIS_CFLAGS)
|
||||
FINAL_LDFLAGS=$(LDFLAGS) $(REDIS_LDFLAGS) $(DEBUG)
|
||||
FINAL_LIBS=-lm -lcurl
|
||||
FINAL_LIBS+=-lm -lcurl
|
||||
DEBUG=-g -ggdb
|
||||
|
||||
ifeq ($(uname_S),SunOS)
|
||||
@@ -206,9 +210,9 @@ MAKECOLOR="\033[32;1m"
|
||||
ENDCOLOR="\033[0m"
|
||||
|
||||
ifndef V
|
||||
QUIET_CC = @printf ' %b %b\n' $(CCCOLOR)CC$(ENDCOLOR) $(SRCCOLOR)$@$(ENDCOLOR) 1>&2;
|
||||
QUIET_LINK = @printf ' %b %b\n' $(LINKCOLOR)LINK$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR) 1>&2;
|
||||
QUIET_INSTALL = @printf ' %b %b\n' $(LINKCOLOR)INSTALL$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR) 1>&2;
|
||||
QUIET_CC = @printf ' %b %b\n' $(CCCOLOR)CC$(ENDCOLOR) $(SRCCOLOR)$@$(ENDCOLOR);
|
||||
QUIET_LINK = @printf ' %b %b\n' $(LINKCOLOR)LINK$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR);
|
||||
QUIET_INSTALL = @printf ' %b %b\n' $(LINKCOLOR)INSTALL$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR);
|
||||
endif
|
||||
|
||||
REDIS_SERVER_NAME=keydb-server
|
||||
|
||||
@@ -1496,8 +1496,15 @@ void configGetCommand(client *c) {
|
||||
listIter li;
|
||||
listNode *ln;
|
||||
listRewind(g_pserver->masters, &li);
|
||||
bool fFirst = true;
|
||||
while ((ln = listNext(&li)))
|
||||
{
|
||||
if (!fFirst)
|
||||
{
|
||||
addReplyBulkCString(c,optname);
|
||||
matches++;
|
||||
}
|
||||
fFirst = false;
|
||||
struct redisMaster *mi = (struct redisMaster*)listNodeValue(ln);
|
||||
snprintf(buf,sizeof(buf),"%s %d",
|
||||
mi->masterhost, mi->masterport);
|
||||
|
||||
@@ -135,6 +135,15 @@ void activeExpireCycleExpire(redisDb *db, expireEntry &e, long long now) {
|
||||
|
||||
if (deleted)
|
||||
{
|
||||
if (!pfat->FEmpty())
|
||||
{
|
||||
// We need to resort the expire entry since it may no longer be in the correct position
|
||||
auto itr = db->setexpire->find(e.key());
|
||||
expireEntry eT = std::move(e);
|
||||
db->setexpire->erase(itr);
|
||||
db->setexpire->insert(eT);
|
||||
}
|
||||
|
||||
robj objT;
|
||||
switch (val->type)
|
||||
{
|
||||
|
||||
+67
-26
@@ -27,6 +27,7 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "fmacros.h"
|
||||
#include "fastlock.h"
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
@@ -43,6 +44,7 @@
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <TargetConditionals.h>
|
||||
@@ -60,6 +62,11 @@
|
||||
#define UNUSED(x) ((void)x)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BACKTRACE
|
||||
#include <ucontext.h>
|
||||
__attribute__((weak)) void logStackTrace(ucontext_t *) {}
|
||||
#endif
|
||||
|
||||
extern int g_fInCrash;
|
||||
|
||||
/****************************************************
|
||||
@@ -149,6 +156,43 @@ __attribute__((weak)) void serverLog(int , const char *fmt, ...)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
extern "C" pid_t gettid()
|
||||
{
|
||||
static thread_local int pidCache = -1;
|
||||
#ifdef __linux__
|
||||
if (pidCache == -1)
|
||||
pidCache = syscall(SYS_gettid);
|
||||
#else
|
||||
if (pidCache == -1) {
|
||||
uint64_t tidT;
|
||||
pthread_threadid_np(nullptr, &tidT);
|
||||
assert(tidT < UINT_MAX);
|
||||
pidCache = (int)tidT;
|
||||
}
|
||||
#endif
|
||||
return pidCache;
|
||||
}
|
||||
|
||||
void printTrace()
|
||||
{
|
||||
#ifdef HAVE_BACKTRACE
|
||||
serverLog(3 /*LL_WARNING*/, "printing backtrace for thread %d", gettid());
|
||||
ucontext_t ctxt;
|
||||
getcontext(&ctxt);
|
||||
logStackTrace(&ctxt);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
static int futex(volatile unsigned *uaddr, int futex_op, int val,
|
||||
const struct timespec *timeout, int val3)
|
||||
{
|
||||
return syscall(SYS_futex, uaddr, futex_op, val,
|
||||
timeout, uaddr, val3);
|
||||
}
|
||||
#endif
|
||||
|
||||
class DeadlockDetector
|
||||
{
|
||||
std::map<pid_t, fastlock *> m_mapwait;
|
||||
@@ -156,9 +200,19 @@ class DeadlockDetector
|
||||
public:
|
||||
void registerwait(fastlock *lock, pid_t thispid)
|
||||
{
|
||||
static volatile bool fInDeadlock = false;
|
||||
|
||||
if (lock == &m_lock || g_fInCrash)
|
||||
return;
|
||||
fastlock_lock(&m_lock);
|
||||
|
||||
if (fInDeadlock)
|
||||
{
|
||||
printTrace();
|
||||
fastlock_unlock(&m_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
m_mapwait.insert(std::make_pair(thispid, lock));
|
||||
|
||||
// Detect cycles
|
||||
@@ -184,6 +238,19 @@ public:
|
||||
if (pidCheck == thispid)
|
||||
break;
|
||||
}
|
||||
// Wake All sleeping threads so they can print their callstacks
|
||||
#ifdef HAVE_BACKTRACE
|
||||
#ifdef __linux__
|
||||
int mask = -1;
|
||||
fInDeadlock = true;
|
||||
fastlock_unlock(&m_lock);
|
||||
futex(&lock->m_ticket.u, FUTEX_WAKE_BITSET_PRIVATE, INT_MAX, nullptr, mask);
|
||||
futex(&itr->second->m_ticket.u, FUTEX_WAKE_BITSET_PRIVATE, INT_MAX, nullptr, mask);
|
||||
sleep(2);
|
||||
fastlock_lock(&m_lock);
|
||||
printTrace();
|
||||
#endif
|
||||
#endif
|
||||
serverLog(3 /*LL_WARNING*/, "!!! KeyDB Will Now Crash !!!");
|
||||
_serverPanic(__FILE__, __LINE__, "Deadlock detected");
|
||||
}
|
||||
@@ -222,32 +289,6 @@ uint64_t fastlock_getlongwaitcount()
|
||||
return rval;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
static int futex(volatile unsigned *uaddr, int futex_op, int val,
|
||||
const struct timespec *timeout, int val3)
|
||||
{
|
||||
return syscall(SYS_futex, uaddr, futex_op, val,
|
||||
timeout, uaddr, val3);
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C" pid_t gettid()
|
||||
{
|
||||
static thread_local int pidCache = -1;
|
||||
#ifdef __linux__
|
||||
if (pidCache == -1)
|
||||
pidCache = syscall(SYS_gettid);
|
||||
#else
|
||||
if (pidCache == -1) {
|
||||
uint64_t tidT;
|
||||
pthread_threadid_np(nullptr, &tidT);
|
||||
assert(tidT < UINT_MAX);
|
||||
pidCache = (int)tidT;
|
||||
}
|
||||
#endif
|
||||
return pidCache;
|
||||
}
|
||||
|
||||
extern "C" void fastlock_sleep(fastlock *lock, pid_t pid, unsigned wake, unsigned mask)
|
||||
{
|
||||
#ifdef __linux__
|
||||
|
||||
+13
-2
@@ -23,7 +23,7 @@ static const char *szMotdCachePath()
|
||||
return "";
|
||||
const char *homedir = pw->pw_dir;
|
||||
sdsMotdCachePath = sdsnew(homedir);
|
||||
sdsMotdCachePath = sdscat(sdsMotdCachePath, "/.keydb-cli-motd");
|
||||
sdsMotdCachePath = sdscat(sdsMotdCachePath, motd_cache_file);
|
||||
return sdsMotdCachePath;
|
||||
}
|
||||
static size_t motd_write_callback(void *ptr, size_t size, size_t nmemb, sds *str)
|
||||
@@ -87,7 +87,7 @@ extern "C" char *fetchMOTD(int cache)
|
||||
str = sdsnew("");
|
||||
curl = curl_easy_init();
|
||||
if(curl) {
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "http://api.keydb.dev/motd/motd.txt");
|
||||
curl_easy_setopt(curl, CURLOPT_URL, motd_url);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // follow redirects
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 2); // take no more than two seconds
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, motd_write_callback);
|
||||
@@ -101,6 +101,17 @@ extern "C" char *fetchMOTD(int cache)
|
||||
sdsfree(str);
|
||||
str = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
long response_code;
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
|
||||
if ((response_code / 100) != 2)
|
||||
{
|
||||
// An error code not in the 200s implies an error
|
||||
sdsfree(str);
|
||||
str = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
extern const char *motd_url;
|
||||
extern const char *motd_cache_file;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
+26
-12
@@ -496,7 +496,7 @@ void addReplyErrorLengthCore(client *c, const char *s, size_t len, bool fAsync)
|
||||
|
||||
if (c->querybuf && sdslen(c->querybuf)) {
|
||||
std::string str = escapeString(c->querybuf);
|
||||
serverLog(LL_WARNING, "\tquerybuf: %s", str.c_str());
|
||||
printf("\tquerybuf: %s\n", str.c_str());
|
||||
}
|
||||
c->master_error = 1;
|
||||
}
|
||||
@@ -1633,7 +1633,10 @@ void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask) {
|
||||
c->lock.lock();
|
||||
ae.arm(c);
|
||||
if (c->flags & CLIENT_CLOSE_ASAP)
|
||||
freeClient(c);
|
||||
{
|
||||
if (!freeClient(c))
|
||||
c->lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3104,12 +3107,23 @@ int processEventsWhileBlocked(int iel) {
|
||||
int iterations = 4; /* See the function top-comment. */
|
||||
int count = 0;
|
||||
|
||||
client *c = serverTL->current_client;
|
||||
if (c != nullptr)
|
||||
std::vector<client*> vecclients;
|
||||
listIter li;
|
||||
listNode *ln;
|
||||
listRewind(g_pserver->clients, &li);
|
||||
|
||||
// All client locks must be acquired *after* the global lock is reacquired to prevent deadlocks
|
||||
// so unlock here, and save them for reacquisition later
|
||||
while ((ln = listNext(&li)) != nullptr)
|
||||
{
|
||||
serverAssert(c->flags & CLIENT_PROTECTED);
|
||||
c->lock.unlock();
|
||||
client *c = (client*)listNodeValue(ln);
|
||||
if (c->lock.fOwnLock()) {
|
||||
serverAssert(c->flags & CLIENT_PROTECTED); // If the client is not protected we have no gurantee they won't be free'd in the event loop
|
||||
c->lock.unlock();
|
||||
vecclients.push_back(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
aeReleaseLock();
|
||||
try
|
||||
@@ -3126,18 +3140,18 @@ int processEventsWhileBlocked(int iel) {
|
||||
{
|
||||
// Caller expects us to be locked so fix and rethrow
|
||||
AeLocker locker;
|
||||
if (c != nullptr)
|
||||
c->lock.lock();
|
||||
locker.arm(c);
|
||||
locker.arm(nullptr);
|
||||
locker.release();
|
||||
for (client *c : vecclients)
|
||||
c->lock.lock();
|
||||
throw;
|
||||
}
|
||||
|
||||
AeLocker locker;
|
||||
if (c != nullptr)
|
||||
c->lock.lock();
|
||||
locker.arm(c);
|
||||
locker.arm(nullptr);
|
||||
locker.release();
|
||||
for (client *c : vecclients)
|
||||
c->lock.lock();
|
||||
return count;
|
||||
}
|
||||
|
||||
+15
-3
@@ -2095,7 +2095,7 @@ int rdbLoadRio(rio *rdb, rdbSaveInfo *rsi, int loading_aof) {
|
||||
incrRefCount(subexpireKey);
|
||||
} else if (!strcasecmp(szFromObj(auxkey), "keydb-subexpire-when")) {
|
||||
if (key == nullptr || subexpireKey == nullptr) {
|
||||
serverLog(LL_WARNING, "Corrupt subexpire entry in RDB skipping.");
|
||||
serverLog(LL_WARNING, "Corrupt subexpire entry in RDB skipping. key: %s subkey: %s", key != nullptr ? szFromObj(key) : "(null)", subexpireKey != nullptr ? szFromObj(subexpireKey) : "(null)");
|
||||
}
|
||||
else {
|
||||
setExpire(NULL, db, key, subexpireKey, strtoll(szFromObj(auxval), nullptr, 10));
|
||||
@@ -2187,8 +2187,6 @@ int rdbLoadRio(rio *rdb, rdbSaveInfo *rsi, int loading_aof) {
|
||||
decrRefCount(val);
|
||||
val = nullptr;
|
||||
}
|
||||
decrRefCount(key);
|
||||
key = nullptr;
|
||||
}
|
||||
|
||||
/* Reset the state that is key-specified and is populated by
|
||||
@@ -2199,7 +2197,10 @@ int rdbLoadRio(rio *rdb, rdbSaveInfo *rsi, int loading_aof) {
|
||||
}
|
||||
|
||||
if (key != nullptr)
|
||||
{
|
||||
decrRefCount(key);
|
||||
key = nullptr;
|
||||
}
|
||||
|
||||
if (subexpireKey != nullptr)
|
||||
{
|
||||
@@ -2226,6 +2227,17 @@ int rdbLoadRio(rio *rdb, rdbSaveInfo *rsi, int loading_aof) {
|
||||
return C_OK;
|
||||
|
||||
eoferr: /* unexpected end of file is handled here with a fatal exit */
|
||||
if (key != nullptr)
|
||||
{
|
||||
decrRefCount(key);
|
||||
key = nullptr;
|
||||
}
|
||||
if (subexpireKey != nullptr)
|
||||
{
|
||||
decrRefCount(subexpireKey);
|
||||
subexpireKey = nullptr;
|
||||
}
|
||||
|
||||
serverLog(LL_WARNING,"Short read or OOM loading DB. Unrecoverable error, aborting now.");
|
||||
rdbExitReportCorruptRDB("Unexpected EOF reading RDB file");
|
||||
return C_ERR; /* Just to avoid warning */
|
||||
|
||||
@@ -93,6 +93,9 @@ int spectrum_palette_size;
|
||||
|
||||
int g_fInCrash = 0;
|
||||
|
||||
const char *motd_url = "http://api.keydb.dev/motd/motd_cli.txt";
|
||||
const char *motd_cache_file = "/.keydb-cli-motd";
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Utility functions
|
||||
*--------------------------------------------------------------------------- */
|
||||
|
||||
+22
-32
@@ -357,8 +357,8 @@ void replicationFeedSlaves(list *slaves, int dictid, robj **argv, int argc) {
|
||||
char szMvcc[128];
|
||||
incrementMvccTstamp();
|
||||
uint64_t mvccTstamp = getMvccTstamp();
|
||||
int cchMvccNum = snprintf(szMvcc, sizeof(szMvcc), "%lu", mvccTstamp);
|
||||
int cchMvcc = snprintf(szMvcc, sizeof(szMvcc), "$%d\r\n%lu\r\n", cchMvccNum, mvccTstamp);
|
||||
int cchMvccNum = snprintf(szMvcc, sizeof(szMvcc), "%" PRIu64, mvccTstamp);
|
||||
int cchMvcc = snprintf(szMvcc, sizeof(szMvcc), "$%d\r\n%" PRIu64 "\r\n", cchMvccNum, mvccTstamp);
|
||||
cchMvcc = std::min<int>(cchMvcc, sizeof(szMvcc)); // tricky snprintf
|
||||
|
||||
/* Write the command to the replication backlog if any. */
|
||||
@@ -2425,8 +2425,6 @@ void freeMasterInfo(redisMaster *mi)
|
||||
{
|
||||
zfree(mi->masterauth);
|
||||
zfree(mi->masteruser);
|
||||
if (mi->clientFake)
|
||||
freeClient(mi->clientFake);
|
||||
delete mi->staleKeyMap;
|
||||
zfree(mi);
|
||||
}
|
||||
@@ -2484,11 +2482,6 @@ void replicationHandleMasterDisconnection(redisMaster *mi) {
|
||||
mi->master = NULL;
|
||||
mi->repl_state = REPL_STATE_CONNECT;
|
||||
mi->repl_down_since = g_pserver->unixtime;
|
||||
if (mi->clientFake) {
|
||||
freeClient(mi->clientFake);
|
||||
mi->clientFake = nullptr;
|
||||
|
||||
}
|
||||
/* We lost connection with our master, don't disconnect slaves yet,
|
||||
* maybe we'll be able to PSYNC with our master later. We'll disconnect
|
||||
* the slaves only if we'll have to do a full resync with our master. */
|
||||
@@ -3378,8 +3371,13 @@ bool FInReplicaReplay()
|
||||
return s_pstate != nullptr && s_pstate->nesting() > 0;
|
||||
}
|
||||
|
||||
struct RemoteMasterState
|
||||
{
|
||||
uint64_t mvcc = 0;
|
||||
client *cFake = nullptr;
|
||||
};
|
||||
|
||||
static std::unordered_map<std::string, uint64_t> g_mapmvcc;
|
||||
static std::unordered_map<std::string, RemoteMasterState> g_mapremote;
|
||||
|
||||
void replicaReplayCommand(client *c)
|
||||
{
|
||||
@@ -3455,12 +3453,15 @@ void replicaReplayCommand(client *c)
|
||||
if (!s_pstate->FPush())
|
||||
return;
|
||||
|
||||
redisMaster *mi = s_pstate->getMi(c);
|
||||
client *cFake = mi->clientFake;
|
||||
if (mi->clientFakeNesting != s_pstate->nesting())
|
||||
cFake = nullptr;
|
||||
serverAssert(mi != nullptr);
|
||||
if (mvcc != 0 && g_mapmvcc[uuid] >= mvcc)
|
||||
RemoteMasterState &remoteState = g_mapremote[uuid];
|
||||
if (remoteState.cFake == nullptr)
|
||||
remoteState.cFake = createClient(-1, c->iel);
|
||||
else
|
||||
remoteState.cFake->iel = c->iel;
|
||||
|
||||
client *cFake = remoteState.cFake;
|
||||
|
||||
if (mvcc != 0 && remoteState.mvcc >= mvcc)
|
||||
{
|
||||
s_pstate->Cancel();
|
||||
s_pstate->Pop();
|
||||
@@ -3469,8 +3470,6 @@ void replicaReplayCommand(client *c)
|
||||
|
||||
// OK We've recieved a command lets execute
|
||||
client *current_clientSave = serverTL->current_client;
|
||||
if (cFake == nullptr)
|
||||
cFake = createClient(-1, c->iel);
|
||||
cFake->lock.lock();
|
||||
cFake->authenticated = c->authenticated;
|
||||
cFake->puser = c->puser;
|
||||
@@ -3483,13 +3482,15 @@ void replicaReplayCommand(client *c)
|
||||
bool fExec = ccmdPrev != serverTL->commandsExecuted;
|
||||
cFake->lock.unlock();
|
||||
if (cFake->master_error)
|
||||
addReplyError(c, "Error in rreplay command, please check logs");
|
||||
{
|
||||
addReplyError(c, "Error in rreplay command, please check logs.");
|
||||
}
|
||||
if (fExec || cFake->flags & CLIENT_MULTI)
|
||||
{
|
||||
addReply(c, shared.ok);
|
||||
selectDb(c, cFake->db->id);
|
||||
if (mvcc > g_mapmvcc[uuid])
|
||||
g_mapmvcc[uuid] = mvcc;
|
||||
if (mvcc > remoteState.mvcc)
|
||||
remoteState.mvcc = mvcc;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3497,17 +3498,6 @@ void replicaReplayCommand(client *c)
|
||||
addReplyError(c, "command did not execute");
|
||||
}
|
||||
serverAssert(sdslen(cFake->querybuf) == 0);
|
||||
if (cFake->flags & CLIENT_MULTI)
|
||||
{
|
||||
mi->clientFake = cFake;
|
||||
mi->clientFakeNesting = s_pstate->nesting();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mi->clientFake == cFake)
|
||||
mi->clientFake = nullptr;
|
||||
freeClient(cFake);
|
||||
}
|
||||
serverTL->current_client = current_clientSave;
|
||||
|
||||
// call() will not propogate this for us, so we do so here
|
||||
|
||||
+14
-9
@@ -65,6 +65,8 @@
|
||||
#include "motd.h"
|
||||
|
||||
int g_fTestMode = false;
|
||||
const char *motd_url = "http://api.keydb.dev/motd/motd_server.txt";
|
||||
const char *motd_cache_file = "/.keydb-server-motd";
|
||||
|
||||
/* Our shared "common" objects */
|
||||
|
||||
@@ -1037,6 +1039,7 @@ struct redisCommand redisCommandTable[] = {
|
||||
/* We use a private localtime implementation which is fork-safe. The logging
|
||||
* function of Redis may be called from other threads. */
|
||||
extern "C" void nolocks_localtime(struct tm *tmp, time_t t, time_t tz, int dst);
|
||||
extern "C" pid_t gettid();
|
||||
|
||||
/* Low level logging. To use only for very big messages, otherwise
|
||||
* serverLog() is to prefer. */
|
||||
@@ -1074,8 +1077,8 @@ void serverLogRaw(int level, const char *msg) {
|
||||
} else {
|
||||
role_char = (listLength(g_pserver->masters) ? 'S':'M'); /* Slave or Master. */
|
||||
}
|
||||
fprintf(fp,"%d:%c %s %c %s\n",
|
||||
(int)getpid(),role_char, buf,c[level],msg);
|
||||
fprintf(fp,"%d:%d:%c %s %c %s\n",
|
||||
(int)getpid(),(int)gettid(),role_char, buf,c[level],msg);
|
||||
}
|
||||
fflush(fp);
|
||||
|
||||
@@ -3590,12 +3593,12 @@ int processCommand(client *c, int callFlags) {
|
||||
return C_OK;
|
||||
}
|
||||
}
|
||||
|
||||
incrementMvccTstamp();
|
||||
|
||||
if (!locker.isArmed())
|
||||
locker.arm(c);
|
||||
|
||||
incrementMvccTstamp();
|
||||
|
||||
/* Handle the maxmemory directive.
|
||||
*
|
||||
* Note that we do not want to reclaim memory if we are here re-entering
|
||||
@@ -3679,7 +3682,8 @@ int processCommand(client *c, int callFlags) {
|
||||
* link with master. */
|
||||
if (FBrokenLinkToMaster() &&
|
||||
g_pserver->repl_serve_stale_data == 0 &&
|
||||
!(c->cmd->flags & CMD_STALE))
|
||||
!(c->cmd->flags & CMD_STALE)
|
||||
&& !(g_pserver->fActiveReplica && c->cmd->proc == syncCommand))
|
||||
{
|
||||
flagTransaction(c);
|
||||
addReply(c, shared.masterdownerr);
|
||||
@@ -5015,14 +5019,15 @@ void incrementMvccTstamp()
|
||||
msPrev >>= MVCC_MS_SHIFT; // convert to milliseconds
|
||||
|
||||
long long mst;
|
||||
__atomic_load(&g_pserver->mstime, &mst, __ATOMIC_RELAXED);
|
||||
__atomic_load(&g_pserver->mstime, &mst, __ATOMIC_ACQUIRE);
|
||||
if (msPrev >= (uint64_t)mst) // we can be greater if the count overflows
|
||||
{
|
||||
atomicIncr(g_pserver->mvcc_tstamp, 1);
|
||||
__atomic_fetch_add(&g_pserver->mvcc_tstamp, 1, __ATOMIC_RELEASE);
|
||||
}
|
||||
else
|
||||
{
|
||||
atomicSet(g_pserver->mvcc_tstamp, ((uint64_t)g_pserver->mstime) << MVCC_MS_SHIFT);
|
||||
uint64_t val = ((uint64_t)g_pserver->mstime) << MVCC_MS_SHIFT;
|
||||
__atomic_store(&g_pserver->mvcc_tstamp, &val, __ATOMIC_RELEASE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5033,7 +5038,7 @@ void OnTerminate()
|
||||
The easiest way to achieve that is to acutally segfault, so we assert
|
||||
here.
|
||||
*/
|
||||
serverAssert(false);
|
||||
serverPanic("std::teminate() called");
|
||||
}
|
||||
|
||||
void *workerThreadMain(void *parg)
|
||||
|
||||
@@ -1541,8 +1541,6 @@ struct redisMaster {
|
||||
int masterport; /* Port of master */
|
||||
client *cached_master; /* Cached master to be reused for PSYNC. */
|
||||
client *master;
|
||||
client *clientFake;
|
||||
int clientFakeNesting;
|
||||
/* The following two fields is where we store master PSYNC replid/offset
|
||||
* while the PSYNC is in progress. At the end we'll copy the fields into
|
||||
* the server->master client structure. */
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
#define KEYDB_REAL_VERSION "5.3.2"
|
||||
#define KEYDB_REAL_VERSION "5.3.3"
|
||||
extern const char *KEYDB_SET_VERSION; // Unlike real version, this can be overriden by the config
|
||||
|
||||
+13
-4
@@ -220,7 +220,7 @@ start_server {tags {"expire"}} {
|
||||
assert {$ttl <= 98 && $ttl > 90}
|
||||
}
|
||||
|
||||
test { EXPIREMEMBER works (set) } {
|
||||
test {EXPIREMEMBER works (set)} {
|
||||
r flushall
|
||||
r sadd testkey foo bar baz
|
||||
r expiremember testkey foo 1
|
||||
@@ -228,7 +228,7 @@ start_server {tags {"expire"}} {
|
||||
assert_equal {2} [r scard testkey]
|
||||
}
|
||||
|
||||
test { EXPIREMEMBER works (hash) } {
|
||||
test {EXPIREMEMBER works (hash)} {
|
||||
r flushall
|
||||
r hset testkey foo bar
|
||||
r expiremember testkey foo 1
|
||||
@@ -236,7 +236,7 @@ start_server {tags {"expire"}} {
|
||||
r exists testkey
|
||||
} {0}
|
||||
|
||||
test { EXPIREMEMBER works (zset) } {
|
||||
test {EXPIREMEMBER works (zset)} {
|
||||
r flushall
|
||||
r zadd testkey 1 foo
|
||||
r zadd testkey 2 bar
|
||||
@@ -246,10 +246,19 @@ start_server {tags {"expire"}} {
|
||||
assert_equal {1} [r zcard testkey]
|
||||
}
|
||||
|
||||
test { TTL for subkey expires works } {
|
||||
test {TTL for subkey expires works} {
|
||||
r flushall
|
||||
r sadd testkey foo bar baz
|
||||
r expiremember testkey foo 10000
|
||||
assert [expr [r ttl testkey foo] > 0]
|
||||
}
|
||||
|
||||
test {Roundtrip for subkey expires works} {
|
||||
r flushall
|
||||
r sadd testkey foo bar baz
|
||||
r expiremember testkey foo 10000
|
||||
r save
|
||||
r debug reload
|
||||
assert [expr [r ttl testkey foo] > 0]
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user