Compare commits

...
Author SHA1 Message Date
christianEQ 0ae13c9731 tabs -> spaces 2021-07-12 18:55:44 +00:00
christianEQ f1f52af9cf fix for #323: seg fault on expiremember 2021-07-08 02:50:05 +00:00
John Sully 0a56a73bd9 Prevent test code crash due to no log data 2021-06-14 22:06:36 +00:00
John Sully 3a1d3090f2 active defrag tests need to run single threaded because jemalloc has seperate mempools per thread and the numbers won't match otherwise 2021-06-14 16:32:47 +00:00
John Sully b1f662d639 Don't pass on flags indicating membership in a list 2021-05-30 05:11:18 +00:00
John Sully aa5b27b040 Fix a leak in the benchmark 2021-05-30 02:55:39 +00:00
John Sully 10d254ec1b Fix merge issue with module test script 2021-05-30 02:45:06 +00:00
John Sully e8a44821d0 Ensure our connections are touched only on the right thread 2021-05-30 02:08:30 +00:00
John Sully 92e48f0717 Handle race where a different thread cancels the replication but we haven't closed the connection 2021-05-30 02:08:02 +00:00
John Sully 9742c44db5 Delete pipe on the right thread so event handlers are cleaned up 2021-05-30 02:07:31 +00:00
John Sully 5d16f51950 Don't leave dangling client pointers in the process list 2021-05-30 02:06:47 +00:00
John Sully 1ed2e8b5bc Don't leak AE control pipes to fork children 2021-05-30 02:06:20 +00:00
John Sully b20803b766 Fix branding 2021-05-29 07:08:01 +00:00
John Sully 8cf1daf823 Fix cluster test failures 2021-05-29 07:07:54 +00:00
John Sully 083b54472c Mac build break fixes 2021-05-28 22:40:03 -04:00
John Sully 1b9fea0669 Prevent partial sync in test that requires only full syncs 2021-05-29 02:22:20 +00:00
John Sully d3c37c7159 Fix failover command test failures 2021-05-29 01:19:12 +00:00
John Sully 807f020184 Remove dup'd code from merge 2021-05-29 01:08:52 +00:00
John Sully b400be68b7 ProcessingEventsWhileBlocked is relevant only to the current thread 2021-05-29 01:08:43 +00:00
John Sully e39bdb58ec Make processClients reentrant 2021-05-29 01:08:14 +00:00
John Sully 83c8977033 Don't have dangling expires 2021-05-29 01:07:46 +00:00
John Sully 682990eeb3 Use correct make flags 2021-05-29 01:07:35 +00:00
John Sully 7ee766aee1 Ensure multi-thread handling of cached master is equivalent to single thread case 2021-05-26 17:29:47 +00:00
John Sully 848c5ad784 Avoid differences between single thread and multi-thread 2021-05-26 17:29:01 +00:00
John Sully a41fb1b036 Eliminate test issue while clients wait for async free 2021-05-26 01:18:47 +00:00
26 changed files with 130 additions and 444 deletions

No files matched your search

+3 -3
View File
@@ -12,7 +12,7 @@ jobs:
run: |
sudo apt-get update
sudo apt-get -y install uuid-dev libcurl4-openssl-dev
make REDIS_CFLAGS='-Werror' BUILD_TLS=yes -j2
make KEYDB_CFLAGS='-Werror' KEYDB_CXXFLAGS='-Werror' BUILD_TLS=yes -j2
- name: gen-cert
run: ./utils/gen-test-certs.sh
- name: test-tls
@@ -44,7 +44,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: make
run: make REDIS_CFLAGS='-Werror' -j2
run: make KEYDB_CFLAGS='-Werror' KEYDB_CXXFLAGS='-Werror' -j2
build-libc-malloc:
runs-on: ubuntu-latest
@@ -54,5 +54,5 @@ jobs:
run: |
sudo apt-get update
sudo apt-get -y install uuid-dev libcurl4-openssl-dev
make REDIS_CFLAGS='-Werror' MALLOC=libc -j2
make KEYDB_CFLAGS='-Werror' KEYDB_CXXFLAGS='-Werror' MALLOC=libc -j2
-308
View File
@@ -1,308 +0,0 @@
name: Daily
on:
pull_request:
branches:
# any PR to a release branch.
- '[0-9].[0-9]'
schedule:
- cron: '0 0 * * *'
jobs:
test-ubuntu-jemalloc:
runs-on: ubuntu-latest
if: github.repository == 'redis/redis'
timeout-minutes: 14400
steps:
- uses: actions/checkout@v2
- name: make
run: make REDIS_CFLAGS='-Werror -DREDIS_TEST'
- name: test
run: |
sudo apt-get install tcl8.6
./runtest --accurate --verbose --dump-logs
- name: module api test
run: ./runtest-moduleapi --verbose
- name: sentinel tests
run: ./runtest-sentinel
- name: cluster tests
run: ./runtest-cluster
- name: unittest
run: ./src/redis-server test all
test-ubuntu-libc-malloc:
runs-on: ubuntu-latest
if: github.repository == 'redis/redis'
timeout-minutes: 14400
steps:
- uses: actions/checkout@v2
- name: make
run: make MALLOC=libc
- name: test
run: |
sudo apt-get install tcl8.6
./runtest --accurate --verbose --dump-logs
- name: module api test
run: ./runtest-moduleapi --verbose
- name: sentinel tests
run: ./runtest-sentinel
- name: cluster tests
run: ./runtest-cluster
test-ubuntu-no-malloc-usable-size:
runs-on: ubuntu-latest
if: github.repository == 'redis/redis'
timeout-minutes: 14400
steps:
- uses: actions/checkout@v2
- name: make
run: make MALLOC=libc CFLAGS=-DNO_MALLOC_USABLE_SIZE
- name: test
run: |
sudo apt-get install tcl8.6
./runtest --accurate --verbose --dump-logs
- name: module api test
run: ./runtest-moduleapi --verbose
- name: sentinel tests
run: ./runtest-sentinel
- name: cluster tests
run: ./runtest-cluster
test-ubuntu-32bit:
runs-on: ubuntu-latest
if: github.repository == 'redis/redis'
timeout-minutes: 14400
steps:
- uses: actions/checkout@v2
- name: make
run: |
sudo apt-get update && sudo apt-get install libc6-dev-i386
make 32bit REDIS_CFLAGS='-Werror -DREDIS_TEST'
- name: test
run: |
sudo apt-get install tcl8.6
./runtest --accurate --verbose --dump-logs
- name: module api test
run: |
make -C tests/modules 32bit # the script below doesn't have an argument, we must build manually ahead of time
./runtest-moduleapi --verbose
- name: sentinel tests
run: ./runtest-sentinel
- name: cluster tests
run: ./runtest-cluster
- name: unittest
run: ./src/redis-server test all
test-ubuntu-tls:
runs-on: ubuntu-latest
if: github.repository == 'redis/redis'
timeout-minutes: 14400
steps:
- uses: actions/checkout@v2
- name: make
run: |
make BUILD_TLS=yes
- name: test
run: |
sudo apt-get install tcl8.6 tcl-tls
./utils/gen-test-certs.sh
./runtest --accurate --verbose --tls --dump-logs
./runtest --accurate --verbose --dump-logs
- name: module api test
run: |
./runtest-moduleapi --verbose --tls
./runtest-moduleapi --verbose
- name: sentinel tests
run: |
./runtest-sentinel --tls
./runtest-sentinel
- name: cluster tests
run: |
./runtest-cluster --tls
./runtest-cluster
test-ubuntu-io-threads:
runs-on: ubuntu-latest
if: github.repository == 'redis/redis'
timeout-minutes: 14400
steps:
- uses: actions/checkout@v2
- name: make
run: |
make
- name: test
run: |
sudo apt-get install tcl8.6 tcl-tls
./runtest --config io-threads 4 --config io-threads-do-reads yes --accurate --verbose --tags network --dump-logs
- name: cluster tests
run: |
./runtest-cluster --config io-threads 4 --config io-threads-do-reads yes
test-valgrind:
runs-on: ubuntu-latest
if: github.repository == 'redis/redis'
timeout-minutes: 14400
steps:
- uses: actions/checkout@v2
- name: make
run: make valgrind REDIS_CFLAGS='-Werror -DREDIS_TEST'
- name: test
run: |
sudo apt-get update
sudo apt-get install tcl8.6 valgrind -y
./runtest --valgrind --verbose --clients 1 --dump-logs
- name: module api test
run: ./runtest-moduleapi --valgrind --no-latency --verbose --clients 1
- name: unittest
run: |
valgrind --track-origins=yes --suppressions=./src/valgrind.sup --show-reachable=no --show-possibly-lost=no --leak-check=full --log-file=err.txt ./src/redis-server test all
if grep -q 0x err.txt; then cat err.txt; exit 1; fi
test-valgrind-no-malloc-usable-size:
runs-on: ubuntu-latest
if: github.repository == 'redis/redis'
timeout-minutes: 14400
steps:
- uses: actions/checkout@v2
- name: make
run: make valgrind CFLAGS="-DNO_MALLOC_USABLE_SIZE"
- name: test
run: |
sudo apt-get update
sudo apt-get install tcl8.6 valgrind -y
./runtest --valgrind --verbose --clients 1 --dump-logs
- name: module api test
run: ./runtest-moduleapi --valgrind --no-latency --verbose --clients 1
test-centos7-jemalloc:
runs-on: ubuntu-latest
if: github.repository == 'redis/redis'
container: centos:7
timeout-minutes: 14400
steps:
- uses: actions/checkout@v2
- name: make
run: |
yum -y install gcc make
make
- name: test
run: |
yum -y install which tcl
./runtest --accurate --verbose --dump-logs
- name: module api test
run: ./runtest-moduleapi --verbose
- name: sentinel tests
run: ./runtest-sentinel
- name: cluster tests
run: ./runtest-cluster
test-centos7-tls:
runs-on: ubuntu-latest
if: github.repository == 'redis/redis'
container: centos:7
timeout-minutes: 14400
steps:
- uses: actions/checkout@v2
- name: make
run: |
yum -y install centos-release-scl epel-release
yum -y install devtoolset-7 openssl-devel openssl
scl enable devtoolset-7 "make BUILD_TLS=yes"
- name: test
run: |
yum -y install tcl tcltls
./utils/gen-test-certs.sh
./runtest --accurate --verbose --tls --dump-logs
./runtest --accurate --verbose --dump-logs
- name: module api test
run: |
./runtest-moduleapi --verbose --tls
./runtest-moduleapi --verbose
- name: sentinel tests
run: |
./runtest-sentinel --tls
./runtest-sentinel
- name: cluster tests
run: |
./runtest-cluster --tls
./runtest-cluster
test-macos-latest:
runs-on: macos-latest
if: github.repository == 'redis/redis'
timeout-minutes: 14400
steps:
- uses: actions/checkout@v2
- name: make
run: make
- name: test
run: |
./runtest --accurate --verbose --no-latency --dump-logs
- name: module api test
run: ./runtest-moduleapi --verbose
- name: sentinel tests
run: ./runtest-sentinel
- name: cluster tests
run: ./runtest-cluster
test-freebsd:
runs-on: macos-latest
if: github.repository == 'redis/redis'
timeout-minutes: 14400
steps:
- uses: actions/checkout@v2
- name: test
uses: vmactions/freebsd-vm@v0.1.2
with:
usesh: true
sync: rsync
prepare: pkg install -y bash gmake lang/tcl86
run: >
gmake &&
./runtest --accurate --verbose --no-latency --dump-logs &&
MAKE=gmake ./runtest-moduleapi --verbose &&
./runtest-sentinel &&
./runtest-cluster
test-alpine-jemalloc:
runs-on: ubuntu-latest
if: github.repository == 'redis/redis'
container: alpine:latest
steps:
- uses: actions/checkout@v2
- name: make
run: |
apk add build-base
make REDIS_CFLAGS='-Werror'
- name: test
run: |
apk add tcl procps
./runtest --accurate --verbose --dump-logs
- name: module api test
run: ./runtest-moduleapi --verbose
- name: sentinel tests
run: ./runtest-sentinel
- name: cluster tests
run: ./runtest-cluster
test-alpine-libc-malloc:
runs-on: ubuntu-latest
if: github.repository == 'redis/redis'
container: alpine:latest
steps:
- uses: actions/checkout@v2
- name: make
run: |
apk add build-base
make REDIS_CFLAGS='-Werror' USE_JEMALLOC=no CFLAGS=-DUSE_MALLOC_USABLE_SIZE
- name: test
run: |
apk add tcl procps
./runtest --accurate --verbose --dump-logs
- name: module api test
run: ./runtest-moduleapi --verbose
- name: sentinel tests
run: ./runtest-sentinel
- name: cluster tests
run: ./runtest-cluster
+13 -13
View File
@@ -13,13 +13,13 @@ Run `make BUILD_TLS=yes`.
### Tests
To run Redis test suite with TLS, you'll need TLS support for TCL (i.e.
To run KeyDB test suite with TLS, you'll need TLS support for TCL (i.e.
`tcl-tls` package on Debian/Ubuntu).
1. Run `./utils/gen-test-certs.sh` to generate a root CA and a server
certificate.
2. Run `./runtest --tls` or `./runtest-cluster --tls` to run Redis and Redis
2. Run `./runtest --tls` or `./runtest-cluster --tls` to run KeyDB and KeyDB
Cluster tests in TLS mode.
### Running manually
@@ -27,23 +27,23 @@ To run Redis test suite with TLS, you'll need TLS support for TCL (i.e.
To manually run a Redis server with TLS mode (assuming `gen-test-certs.sh` was
invoked so sample certificates/keys are available):
./src/redis-server --tls-port 6379 --port 0 \
--tls-cert-file ./tests/tls/redis.crt \
--tls-key-file ./tests/tls/redis.key \
./src/keydb-server --tls-port 6379 --port 0 \
--tls-cert-file ./tests/tls/keydb.crt \
--tls-key-file ./tests/tls/keydb.key \
--tls-ca-cert-file ./tests/tls/ca.crt
To connect to this Redis server with `redis-cli`:
To connect to this Redis server with `keydb-cli`:
./src/redis-cli --tls \
--cert ./tests/tls/redis.crt \
--key ./tests/tls/redis.key \
./src/keydb-cli --tls \
--cert ./tests/tls/keydb.crt \
--key ./tests/tls/keydb.key \
--cacert ./tests/tls/ca.crt
This will disable TCP and enable TLS on port 6379. It's also possible to have
both TCP and TLS available, but you'll need to assign different ports.
To make a Replica connect to the master using TLS, use `--tls-replication yes`,
and to make Redis Cluster use TLS across nodes use `--tls-cluster yes`.
and to make KeyDB Cluster use TLS across nodes use `--tls-cluster yes`.
Connections
-----------
@@ -56,18 +56,18 @@ Note that unlike Redis, KeyDB fully supports multithreading of TLS connections.
To-Do List
----------
- [ ] redis-benchmark support. The current implementation is a mix of using
- [ ] keydb-benchmark support. The current implementation is a mix of using
hiredis for parsing and basic networking (establishing connections), but
directly manipulating sockets for most actions. This will need to be cleaned
up for proper TLS support. The best approach is probably to migrate to hiredis
async mode.
- [ ] redis-cli `--slave` and `--rdb` support.
- [ ] keydb-cli `--slave` and `--rdb` support.
Multi-port
----------
Consider the implications of allowing TLS to be configured on a separate port,
making Redis listening on multiple ports:
making KeyDB listening on multiple ports:
1. Startup banner port notification
2. Proctitle
-1
View File
@@ -31,7 +31,6 @@ $TCLSH tests/test_helper.tcl \
--single unit/moduleapi/blockedclient \
--single unit/moduleapi/moduleloadsave \
--single unit/moduleapi/getkeys \
--single unit/moduleapi/timers \
--single unit/moduleapi/test_lazyfree \
--single unit/moduleapi/defrag \
--single unit/moduleapi/hash \
+8
View File
@@ -808,3 +808,11 @@ int aeThreadOwnsLock()
{
return g_lock.fOwnLock();
}
void aeClosePipesForForkChild(aeEventLoop *el)
{
close(el->fdCmdRead);
el->fdCmdRead = -1;
close(el->fdCmdWrite);
el->fdCmdWrite = -1;
}
+1
View File
@@ -161,6 +161,7 @@ int aeGetSetSize(aeEventLoop *eventLoop);
aeEventLoop *aeGetCurrentEventLoop();
int aeResizeSetSize(aeEventLoop *eventLoop, int setsize);
void aeSetDontWait(aeEventLoop *eventLoop, int noWait);
void aeClosePipesForForkChild(aeEventLoop *eventLoop);
void setAeLockSetThreadSpinWorker(spin_worker worker);
void aeAcquireLock();
+4
View File
@@ -688,6 +688,7 @@ void freeClusterLink(clusterLink *link) {
}
static void clusterConnAcceptHandler(connection *conn) {
serverAssert(ielFromEventLoop(serverTL->el) == IDX_EVENT_LOOP_MAIN);
clusterLink *link;
if (connGetState(conn) != CONN_STATE_CONNECTED) {
@@ -1791,6 +1792,8 @@ void clusterUpdateSlotsConfigWith(clusterNode *sender, uint64_t senderConfigEpoc
* processing lead to some inconsistency error (for instance a PONG
* received from the wrong sender ID). */
int clusterProcessPacket(clusterLink *link) {
serverAssert(ielFromEventLoop(serverTL->el) == IDX_EVENT_LOOP_MAIN);
clusterMsg *hdr = (clusterMsg*) link->rcvbuf;
uint32_t totlen = ntohl(hdr->totlen);
uint16_t type = ntohs(hdr->type);
@@ -3546,6 +3549,7 @@ void clusterHandleManualFailover(void) {
/* This is executed 10 times every second */
void clusterCron(void) {
serverAssert(ielFromEventLoop(serverTL->el) == IDX_EVENT_LOOP_MAIN);
dictIterator *di;
dictEntry *de;
int update_state = 0;
+4 -1
View File
@@ -256,7 +256,10 @@ void setproctitle(const char *fmt, ...);
#define redis_set_thread_title(name) rename_thread(find_thread(0), name)
#else
#if (defined __APPLE__ && defined(MAC_OS_X_VERSION_10_7))
extern "C" int pthread_setname_np(const char *name);
#ifdef __cplusplus
extern "C"
#endif
int pthread_setname_np(const char *name);
#include <pthread.h>
#define redis_set_thread_title(name) pthread_setname_np(name)
#else
+1 -1
View File
@@ -821,8 +821,8 @@ void expireEntryFat::expireSubKey(const char *szSubkey, long long when)
fFound = true;
}
if (fFound) {
m_vecexpireEntries.erase(itr);
dictDelete(m_dictIndex, szSubkey);
m_vecexpireEntries.erase(itr);
break;
}
++itr;
+4
View File
@@ -304,6 +304,10 @@ uint64_t fastlock_getlongwaitcount()
extern "C" void fastlock_sleep(fastlock *lock, pid_t pid, unsigned wake, unsigned myticket)
{
UNUSED(lock);
UNUSED(pid);
UNUSED(wake);
UNUSED(myticket);
#ifdef __linux__
g_dlock.registerwait(lock, pid);
unsigned mask = (1U << (myticket % 32));
+2 -1
View File
@@ -93,4 +93,5 @@ struct fastlock
#ifdef __cplusplus
static_assert(offsetof(struct fastlock, m_ticket) == 64, "ensure padding is correct");
#endif
#endif
+7
View File
@@ -152,6 +152,13 @@ int dbAsyncDelete(redisDb *db, robj *key) {
if (de) {
robj *val = (robj*)dictGetVal(de);
if (val->FExpires())
{
/* Deleting an entry from the expires dict will not free the sds of
* the key, because it is shared with the main dictionary. */
removeExpireCore(db,key,de);
}
/* Tells the module that the key has been unlinked from the database. */
moduleNotifyKeyUnlink(key,val);
+11 -6
View File
@@ -40,7 +40,7 @@
#include "aelocker.h"
static void setProtocolError(const char *errstr, client *c);
std::atomic<int> ProcessingEventsWhileBlocked {0}; /* See processEventsWhileBlocked(). */
__thread int ProcessingEventsWhileBlocked = 0; /* See processEventsWhileBlocked(). */
/* Return the size consumed from the allocator, for the specified SDS string,
* including internal fragmentation. This function is used in order to compute
@@ -1527,6 +1527,8 @@ void unlinkClient(client *c) {
c->fPendingAsyncWrite = FALSE;
}
serverTL->vecclientsProcess.erase(std::remove(serverTL->vecclientsProcess.begin(), serverTL->vecclientsProcess.end(), c), serverTL->vecclientsProcess.end());
/* Clear the tracking status. */
if (c->flags & CLIENT_TRACKING) disableTracking(c);
}
@@ -2573,7 +2575,9 @@ void processClients()
{
serverAssert(GlobalLocksAcquired());
for (client *c : serverTL->vecclientsProcess) {
while (!serverTL->vecclientsProcess.empty()) {
client *c = serverTL->vecclientsProcess.front();
serverTL->vecclientsProcess.erase(serverTL->vecclientsProcess.begin());
/* There is more data in the client input buffer, continue parsing it
* in case to check if there is a full command to execute. */
std::unique_lock<fastlock> ul(c->lock);
@@ -2740,6 +2744,7 @@ sds getAllClientsInfoString(int type) {
while ((ln = listNext(&li)) != NULL) {
client = reinterpret_cast<struct client*>(listNodeValue(ln));
std::unique_lock<decltype(client->lock)> lock(client->lock);
if (client->flags & CLIENT_CLOSE_ASAP) continue;
if (type != -1 && getClientType(client) != type) continue;
o = catClientInfoString(o,client);
o = sdscatlen(o,"\n",1);
@@ -3739,8 +3744,8 @@ void flushSlavesOutputBuffers(void) {
* In such a case, the duration is set to the maximum and new end time and the
* type is set to the more restrictive type of pause. */
void pauseClients(mstime_t end, pause_type type) {
if (type > serverTL->client_pause_type) {
serverTL->client_pause_type = type;
if (type > g_pserver->client_pause_type) {
g_pserver->client_pause_type = type;
}
if (end > g_pserver->client_pause_end_time) {
@@ -3763,7 +3768,7 @@ void unpauseClients(void) {
listIter li;
client *c;
serverTL->client_pause_type = CLIENT_PAUSE_OFF;
g_pserver->client_pause_type = CLIENT_PAUSE_OFF;
/* Unblock all of the clients so they are reprocessed. */
listRewind(g_pserver->paused_clients,&li);
@@ -3776,7 +3781,7 @@ void unpauseClients(void) {
/* Returns true if clients are paused and false otherwise. */
int areClientsPaused(void) {
return serverTL->client_pause_type != CLIENT_PAUSE_OFF;
return g_pserver->client_pause_type != CLIENT_PAUSE_OFF;
}
/* Checks if the current client pause has elapsed and unpause clients
+5 -1
View File
@@ -2897,7 +2897,11 @@ static void backgroundSaveDoneHandlerSocket(int exitcode, int bysignal) {
}
if (g_pserver->rdb_child_exit_pipe!=-1)
close(g_pserver->rdb_child_exit_pipe);
close(g_pserver->rdb_pipe_read);
auto pipeT = g_pserver->rdb_pipe_read;
aePostFunction(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el, [pipeT]{
aeDeleteFileEvent(serverTL->el, pipeT, AE_READABLE);
close(pipeT);
});
g_pserver->rdb_child_exit_pipe = -1;
g_pserver->rdb_pipe_read = -1;
zfree(g_pserver->rdb_pipe_conns);
+1
View File
@@ -1981,6 +1981,7 @@ int main(int argc, const char **argv) {
if (!config.csv) printf("\n");
} while(config.loop);
zfree(data);
if (config.redis_config != NULL) freeRedisConfig(config.redis_config);
+38 -48
View File
@@ -834,10 +834,7 @@ int masterTryPartialResynchronization(client *c) {
buflen = snprintf(buf,sizeof(buf),"+CONTINUE\r\n");
}
if (connWrite(c->conn,buf,buflen) != buflen) {
if (FCorrectThread(c))
freeClient(c);
else
freeClientAsync(c);
freeClientAsync(c);
return C_OK;
}
psync_len = addReplyReplicationBacklog(c,psync_offset);
@@ -1674,10 +1671,7 @@ void updateSlavesWaitingBgsave(int bgsaveerr, int type)
if (bgsaveerr != C_OK) {
ul.unlock();
if (FCorrectThread(replica))
freeClient(replica);
else
freeClientAsync(replica);
freeClientAsync(replica);
serverLog(LL_WARNING,"SYNC failed. BGSAVE child returned an error");
continue;
}
@@ -1723,10 +1717,7 @@ void updateSlavesWaitingBgsave(int bgsaveerr, int type)
if ((replica->repldbfd = open(g_pserver->rdb_filename,O_RDONLY)) == -1 ||
redis_fstat(replica->repldbfd,&buf) == -1) {
ul.unlock();
if (FCorrectThread(replica))
freeClient(replica);
else
freeClientAsync(replica);
freeClientAsync(replica);
serverLog(LL_WARNING,"SYNC failed. Can't open/stat DB after BGSAVE: %s", strerror(errno));
continue;
}
@@ -1898,14 +1889,25 @@ void replicationCreateMasterClient(redisMaster *mi, connection *conn, int dbid)
void replicationCreateCachedMasterClone(redisMaster *mi) {
serverAssert(mi->master != nullptr);
serverLog(LL_NOTICE, "Creating cache clone of our master");
if ((mi->master->flags & (CLIENT_PROTOCOL_ERROR|CLIENT_BLOCKED))) {
freeClientAsync(mi->master);
mi->master = nullptr;
return;
}
client *c = createClient(nullptr, ielFromEventLoop(serverTL->el));
c->flags |= mi->master->flags;
c->flags |= mi->master->flags & ~(CLIENT_PENDING_WRITE | CLIENT_UNBLOCKED | CLIENT_CLOSE_ASAP);
c->authenticated = mi->master->authenticated;
c->reploff = mi->master->reploff;
c->read_reploff = mi->master->read_reploff;
c->user = mi->master->user;
c->replstate = mi->master->replstate;
c->master_error = mi->master->master_error;
c->psync_initial_offset = mi->master->psync_initial_offset;
c->repldboff = mi->master->repldboff;
c->repldbsize = mi->master->repldbsize;
memcpy(c->uuid, mi->master->uuid, UUID_BINARY_LEN);
memcpy(c->replid, mi->master->replid,
sizeof(mi->master->replid));
@@ -1991,6 +1993,10 @@ void readSyncBulkPayload(connection *conn) {
// Should we update our database, or create from scratch?
int fUpdate = g_pserver->fActiveReplica || g_pserver->enable_multimaster;
redisMaster *mi = (redisMaster*)connGetPrivateData(conn);
if (mi == nullptr) {
// We're about to be free'd so bail out
return;
}
serverAssert(GlobalLocksAcquired());
serverAssert(mi->master == nullptr);
@@ -3175,6 +3181,21 @@ int cancelReplicationHandshake(redisMaster *mi, int reconnect) {
return 1;
}
void disconnectMaster(redisMaster *mi)
{
if (mi->master) {
if (FCorrectThread(mi->master)) {
// This will cache the master and do all that fancy stuff
if (!freeClient(mi->master) && mi->master)
replicationCreateCachedMasterClone(mi);
} else {
// We're not on the same thread so we can't use the freeClient method, instead we have to clone the master
// and cache that clone
replicationCreateCachedMasterClone(mi);
}
}
}
/* Set replication to the specified master address and port. */
struct redisMaster *replicationAddMaster(char *ip, int port) {
// pre-reqs: We must not already have a replica in the list with the same tuple
@@ -3204,17 +3225,7 @@ struct redisMaster *replicationAddMaster(char *ip, int port) {
sdsfree(mi->masterhost);
mi->masterhost = nullptr;
if (mi->master) {
if (FCorrectThread(mi->master)) {
// This will cache the master and do all that fancy stuff
if (!freeClient(mi->master) && mi->master)
replicationCreateCachedMasterClone(mi);
} else {
// We're not on the same thread so we can't use the freeClient method, instead we have to clone the master
// and cache that clone
replicationCreateCachedMasterClone(mi);
}
}
disconnectMaster(mi);
serverAssert(mi->master == nullptr);
if (!g_pserver->fActiveReplica)
disconnectAllBlockedClients(); /* Clients blocked in master, now replica. */
@@ -3289,17 +3300,7 @@ void replicationUnsetMaster(redisMaster *mi) {
* replicationHandleMasterDisconnection which can attempt to re-connect. */
sdsfree(mi->masterhost);
mi->masterhost = NULL;
if (mi->master) {
if (FCorrectThread(mi->master)) {
// This will cache the master and do all that fancy stuff
if (!freeClient(mi->master) && mi->master)
replicationCreateCachedMasterClone(mi);
} else {
// We're not on the same thread so we can't use the freeClient method, instead we have to clone the master
// and cache that clone
replicationCreateCachedMasterClone(mi);
}
}
disconnectMaster(mi);
replicationDiscardCachedMaster(mi);
cancelReplicationHandshake(mi,false);
/* When a slave is turned into a master, the current replication ID
@@ -3677,10 +3678,7 @@ void replicationDiscardCachedMaster(redisMaster *mi) {
serverLog(LL_NOTICE,"Discarding previously cached master state.");
mi->cached_master->flags &= ~CLIENT_MASTER;
if (FCorrectThread(mi->cached_master))
freeClient(mi->cached_master);
else
freeClientAsync(mi->cached_master);
freeClientAsync(mi->cached_master);
mi->cached_master = NULL;
}
@@ -4050,15 +4048,7 @@ void replicationCron(void) {
(time(NULL)-mi->master->lastinteraction) > g_pserver->repl_timeout)
{
serverLog(LL_WARNING,"MASTER timeout: no data nor PING received...");
if (FCorrectThread(mi->master)) {
// This will cache the master and do all that fancy stuff
if (!freeClient(mi->master) && mi->master)
replicationCreateCachedMasterClone(mi);
} else {
// We're not on the same thread so we can't use the freeClient method, instead we have to clone the master
// and cache that clone
replicationCreateCachedMasterClone(mi);
}
disconnectMaster(mi);
}
/* Check if we should connect to a MASTER */
+4
View File
@@ -878,6 +878,10 @@ void sentinelRunPendingScripts(void) {
} else if (pid == 0) {
/* Child */
tlsCleanup();
for (int iel = 0; iel < cserver.cthreads; ++iel) {
aeClosePipesForForkChild(g_pserver->rgthreadvar[iel].el);
}
aeClosePipesForForkChild(g_pserver->modulethreadvar.el);
execve(sj->argv[0],sj->argv,environ);
/* If we are here an error occurred. */
_exit(2); /* Don't retry execution. */
+11 -15
View File
@@ -2341,12 +2341,6 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
* the operation even if completely idle. */
if (g_pserver->tracking_clients) trackingLimitUsedSlots();
/* Resize tracking keys table if needed. This is also done at every
* command execution, but we want to be sure that if the last command
* executed changes the value via CONFIG SET, the server will perform
* the operation even if completely idle. */
if (g_pserver->tracking_clients) trackingLimitUsedSlots();
/* Start a scheduled BGSAVE if the corresponding flag is set. This is
* useful when we are forced to postpone a BGSAVE because an AOF
* rewrite is in progress.
@@ -2471,7 +2465,7 @@ void whileBlockedCron() {
latencyAddSampleIfNeeded("while-blocked-cron",latency);
}
extern std::atomic<int> ProcessingEventsWhileBlocked;
extern __thread int ProcessingEventsWhileBlocked;
/* This function gets called every time Redis is entering the
* main loop of the event driven library, that is, before to sleep
@@ -2582,7 +2576,8 @@ void beforeSleep(struct aeEventLoop *eventLoop) {
/* We may have recieved updates from clients about their current offset. NOTE:
* this can't be done where the ACK is recieved since failover will disconnect
* our clients. */
updateFailoverStatus();
if (iel == IDX_EVENT_LOOP_MAIN)
updateFailoverStatus();
/* Send the invalidation messages to clients participating to the
* client side caching protocol in broadcasting (BCAST) mode. */
@@ -2928,10 +2923,6 @@ void initServerConfig(void) {
for (j = 0; j < CONFIG_OOM_COUNT; j++)
g_pserver->oom_score_adj_values[j] = configOOMScoreAdjValuesDefaults[j];
/* Linux OOM Score config */
for (j = 0; j < CONFIG_OOM_COUNT; j++)
g_pserver->oom_score_adj_values[j] = configOOMScoreAdjValuesDefaults[j];
/* Double constants initialization */
R_Zero = 0.0;
R_PosInf = 1.0/R_Zero;
@@ -3436,7 +3427,6 @@ static void initServerThread(struct redisServerThreadVars *pvar, int fMain)
pvar->cclients = 0;
pvar->in_eval = 0;
pvar->in_exec = 0;
pvar->client_pause_type = CLIENT_PAUSE_OFF;
pvar->el = aeCreateEventLoop(g_pserver->maxclients+CONFIG_FDSET_INCR);
aeSetBeforeSleepProc(pvar->el, beforeSleep, AE_SLEEP_THREADSAFE);
aeSetAfterSleepProc(pvar->el, afterSleep, AE_SLEEP_THREADSAFE);
@@ -3528,6 +3518,7 @@ void initServer(void) {
g_pserver->blocked_last_cron = 0;
g_pserver->replication_allowed = 1;
g_pserver->blocking_op_nesting = 0;
g_pserver->client_pause_type = CLIENT_PAUSE_OFF;
if ((g_pserver->tls_port || g_pserver->tls_replication || g_pserver->tls_cluster)
@@ -4539,8 +4530,8 @@ int processCommand(client *c, int callFlags) {
/* If the server is paused, block the client until
* the pause has ended. Replicas are never paused. */
if (!(c->flags & CLIENT_SLAVE) &&
((serverTL->client_pause_type == CLIENT_PAUSE_ALL) ||
(serverTL->client_pause_type == CLIENT_PAUSE_WRITE && is_may_replicate_command)))
((g_pserver->client_pause_type == CLIENT_PAUSE_ALL) ||
(g_pserver->client_pause_type == CLIENT_PAUSE_WRITE && is_may_replicate_command)))
{
c->bpop.timeout = 0;
blockClient(c,BLOCKED_PAUSE);
@@ -6201,6 +6192,11 @@ void closeChildUnusedResourceAfterFork() {
if (g_pserver->cluster_enabled && g_pserver->cluster_config_file_lock_fd != -1)
close(g_pserver->cluster_config_file_lock_fd); /* don't care if this fails */
for (int iel = 0; iel < cserver.cthreads; ++iel) {
aeClosePipesForForkChild(g_pserver->rgthreadvar[iel].el);
}
aeClosePipesForForkChild(g_pserver->modulethreadvar.el);
/* Clear cserver.pidfile, this is the parent pidfile which should not
* be touched (or deleted) by the child (on exit / crash) */
zfree(cserver.pidfile);
+1 -1
View File
@@ -1480,7 +1480,6 @@ struct redisServerThreadVars {
aeEventLoop *el;
socketFds ipfd; /* TCP socket file descriptors */
socketFds tlsfd; /* TLS socket file descriptors */
pause_type client_pause_type; /* True if clients are currently paused */
int in_eval; /* Are we inside EVAL? */
int in_exec; /* Are we inside EXEC? */
std::vector<client*> clients_pending_write; /* There is to write or install handler. */
@@ -1620,6 +1619,7 @@ struct redisServer {
int propagate_in_transaction; /* Make sure we don't propagate nested MULTI/EXEC */
char *ignore_warnings; /* Config: warnings that should be ignored. */
int client_pause_in_transaction; /* Was a client pause executed during this Exec? */
pause_type client_pause_type; /* True if clients are currently paused */
/* Modules */
::dict *moduleapi; /* Exported core APIs dictionary for modules. */
::dict *sharedapi; /* Like moduleapi but containing the APIs that
@@ -36,7 +36,7 @@ test "Set allow-replica-migration no" {
set master0_id [dict get [get_myself 0] id]
test "Resharding all the master #0 slots away from it" {
set output [exec \
../../../src/redis-cli --cluster rebalance \
../../../src/keydb-cli --cluster rebalance \
127.0.0.1:[get_instance_attrib redis 0 port] \
{*}[rediscli_tls_config "../../../tests"] \
--cluster-weight ${master0_id}=0 >@ stdout ]
@@ -44,7 +44,7 @@ test "Resharding all the master #0 slots away from it" {
test "Wait cluster to be stable" {
wait_for_condition 1000 50 {
[catch {exec ../../../src/redis-cli --cluster \
[catch {exec ../../../src/keydb-cli --cluster \
check 127.0.0.1:[get_instance_attrib redis 0 port] \
{*}[rediscli_tls_config "../../../tests"] \
}] == 0
+5 -5
View File
@@ -8,18 +8,18 @@ proc config_set_all_nodes {keyword value} {
proc fix_cluster {addr} {
set code [catch {
exec ../../../src/redis-cli {*}[rediscli_tls_config "../../../tests"] --cluster fix $addr << yes
exec ../../../src/keydb-cli {*}[rediscli_tls_config "../../../tests"] --cluster fix $addr << yes
} result]
if {$code != 0} {
puts "redis-cli --cluster fix returns non-zero exit code, output below:\n$result"
puts "keydb-cli --cluster fix returns non-zero exit code, output below:\n$result"
}
# Note: redis-cli --cluster fix may return a non-zero exit code if nodes don't agree,
# Note: keydb-cli --cluster fix may return a non-zero exit code if nodes don't agree,
# but we can ignore that and rely on the check below.
assert_cluster_state ok
wait_for_condition 100 100 {
[catch {exec ../../../src/redis-cli {*}[rediscli_tls_config "../../../tests"] --cluster check $addr} result] == 0
[catch {exec ../../../src/keydb-cli {*}[rediscli_tls_config "../../../tests"] --cluster check $addr} result] == 0
} else {
puts "redis-cli --cluster check returns non-zero exit code, output below:\n$result"
puts "keydb-cli --cluster check returns non-zero exit code, output below:\n$result"
fail "Cluster could not settle with configuration"
}
}
+1
View File
@@ -279,6 +279,7 @@ start_server {} {
assert_match *slave* [$node_2 role]
# We will cycle all of our replicas here and force a psync.
after 100
assert_equal [expr [s 0 sync_partial_ok] - $initial_psyncs] 2
assert_equal [expr [s 0 sync_full] - $initial_syncs] 0
+2
View File
@@ -39,6 +39,7 @@ proc show_cluster_status {} {
# all the lists are empty.
#
# regexp {^[0-9]+:[A-Z] [0-9]+ [A-z]+ [0-9]+ ([0-9:.]+) .*} $l - logdate
catch {
while 1 {
# Find the log with smallest time.
set empty 0
@@ -67,6 +68,7 @@ proc show_cluster_status {} {
puts "\[$best port $R_port($best)\] [lindex $log($best) 0]"
set log($best) [lrange $log($best) 1 end]
}
}
}
}
+1 -2
View File
@@ -530,8 +530,7 @@ test {diskless loading short read} {
$master multi
$master client kill type replica
$master set asdf asdf
# the side effect of resizing the backlog is that it is flushed (16k is the min size)
$master config set repl-backlog-size [expr {16384 + $i}]
$master debug truncate-repl-backlog
$master exec
}
# wait for loading to stop (fail)
+1 -1
View File
@@ -395,7 +395,7 @@ start_server {tags {"defrag"} overrides {appendonly yes auto-aof-rewrite-percent
# if the current slab is lower in utilization the defragger would have ended up in stagnation,
# keept running and not move any allocation.
# this test is more consistent on a fresh server with no history
start_server {tags {"defrag"} overrides {save ""}} {
start_server {tags {"defrag"} overrides {save "" server-threads 1}} {
r flushdb
r config resetstat
r config set hz 100
-35
View File
@@ -1,35 +0,0 @@
set testmodule [file normalize tests/modules/timers.so]
set timercount 4000
tags "modules" {
test {Ascending module timers can load in correctly} {
start_server [list overrides [list loadmodule "$testmodule ascending $timercount"]] {
wait_for_condition [expr round($timercount/10)] 20 {
[r timer.elapsed] == $timercount
} else {
fail "Server failed to load in timers with ascending periods"
}
}
}
test {Descending module timers can load in correctly} {
start_server [list overrides [list loadmodule "$testmodule descending $timercount"]] {
wait_for_condition [expr round($timercount/10)] 20 {
[r timer.elapsed] == $timercount
} else {
fail "Server failed to load in timers with descending periods"
}
}
}
test {Module timers with the same period can load in correctly} {
start_server [list overrides [list loadmodule "$testmodule same $timercount"]] {
wait_for_condition [expr round($timercount/10)] 20 {
[r timer.elapsed] == $timercount
} else {
fail "Server failed to load in timers with the same period"
}
}
}
}