Skip to content

Commit 2f65aa2

Browse files
committed
Merge branch 'unstable' into RELEASE_5
2 parents 0a0c214 + f5210a8 commit 2f65aa2

28 files changed

+561
-404
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ FROM ubuntu:18.04
44

55
RUN apt-get update \
66
&& DEBIAN_FRONTEND=noninteractive apt-get install -qqy \
7-
build-essential nasm autotools-dev autoconf libjemalloc-dev tcl tcl-dev uuid-dev \
7+
build-essential nasm autotools-dev autoconf libcurl4-openssl-dev libjemalloc-dev tcl tcl-dev uuid-dev \
88
&& apt-get clean
99

1010
CMD make

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ On the same hardware KeyDB can perform twice as many queries per second as Redis
1818
Why fork Redis?
1919
---------------
2020

21-
KeyDB has a different philosophy on how the codebase should evolve. We feel that ease of use, high performance, and a "batteries included" approach is the best way to create a good user experience. While we have great respect for the Redis maintainers it is our opinion that the Redis approach focusses too much on simplicity of the code base at the expense of complexity for the user. This results in the need for external components and workarounds to solve common problems - resulting in more complexity overall.
21+
KeyDB has a different philosophy on how the codebase should evolve. We feel that ease of use, high performance, and a "batteries included" approach is the best way to create a good user experience. While we have great respect for the Redis maintainers it is our opinion that the Redis approach focuses too much on simplicity of the code base at the expense of complexity for the user. This results in the need for external components and workarounds to solve common problems - resulting in more complexity overall.
2222

2323
Because of this difference of opinion features which are right for KeyDB may not be appropriate for Redis. A fork allows us to explore this new development path and implement features which may never be a part of Redis. KeyDB keeps in sync with upstream Redis changes, and where applicable we upstream bug fixes and changes. It is our hope that the two projects can continue to grow and learn from each other.
2424

src/anet.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ static int anetV6Only(char *err, int s) {
476476
return ANET_OK;
477477
}
478478

479-
static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backlog, int fReusePort)
479+
static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backlog, int fReusePort, int fFirstListen)
480480
{
481481
int s = -1, rv;
482482
char _port[6]; /* strlen("65535") */
@@ -498,8 +498,12 @@ static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backl
498498

499499
if (af == AF_INET6 && anetV6Only(err,s) == ANET_ERR) goto error;
500500
if (anetSetReuseAddr(err,s) == ANET_ERR) goto error;
501-
if (fReusePort && anetSetReusePort(err,s) == ANET_ERR) goto error;
502-
if (anetListen(err,s,p->ai_addr,p->ai_addrlen,backlog) == ANET_ERR) s = ANET_ERR;
501+
if (fReusePort && !fFirstListen && anetSetReusePort(err,s) == ANET_ERR) goto error;
502+
if (anetListen(err,s,p->ai_addr,p->ai_addrlen,backlog) == ANET_ERR) {
503+
s = ANET_ERR;
504+
goto end;
505+
}
506+
if (fReusePort && fFirstListen && anetSetReusePort(err,s) == ANET_ERR) goto error;
503507
goto end;
504508
}
505509
if (p == NULL) {
@@ -515,14 +519,14 @@ static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backl
515519
return s;
516520
}
517521

518-
int anetTcpServer(char *err, int port, char *bindaddr, int backlog, int fReusePort)
522+
int anetTcpServer(char *err, int port, char *bindaddr, int backlog, int fReusePort, int fFirstListen)
519523
{
520-
return _anetTcpServer(err, port, bindaddr, AF_INET, backlog, fReusePort);
524+
return _anetTcpServer(err, port, bindaddr, AF_INET, backlog, fReusePort, fFirstListen);
521525
}
522526

523-
int anetTcp6Server(char *err, int port, char *bindaddr, int backlog, int fReusePort)
527+
int anetTcp6Server(char *err, int port, char *bindaddr, int backlog, int fReusePort, int fFirstListen)
524528
{
525-
return _anetTcpServer(err, port, bindaddr, AF_INET6, backlog, fReusePort);
529+
return _anetTcpServer(err, port, bindaddr, AF_INET6, backlog, fReusePort, fFirstListen);
526530
}
527531

528532
int anetUnixServer(char *err, char *path, mode_t perm, int backlog)

src/anet.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ int anetUnixNonBlockConnect(char *err, char *path);
6262
int anetRead(int fd, char *buf, int count);
6363
int anetResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len);
6464
int anetResolveIP(char *err, char *host, char *ipbuf, size_t ipbuf_len);
65-
int anetTcpServer(char *err, int port, char *bindaddr, int backlog, int fReusePort);
66-
int anetTcp6Server(char *err, int port, char *bindaddr, int backlog, int fReusePort);
65+
int anetTcpServer(char *err, int port, char *bindaddr, int backlog, int fReusePort, int fFirstListen);
66+
int anetTcp6Server(char *err, int port, char *bindaddr, int backlog, int fReusePort, int fFirstListen);
6767
int anetUnixServer(char *err, char *path, mode_t perm, int backlog);
6868
int anetTcpAccept(char *err, int serversock, char *ip, size_t ip_len, int *port);
6969
int anetUnixAccept(char *err, int serversock);

src/aof.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,7 @@ client *createFakeClient(void) {
666666
c->flags = 0;
667667
c->fPendingAsyncWrite = FALSE;
668668
c->btype = BLOCKED_NONE;
669-
/* We set the fake client as a slave waiting for the synchronization
669+
/* We set the fake client as a replica waiting for the synchronization
670670
* so that Redis will not try to send replies to this client. */
671671
c->replstate = SLAVE_STATE_WAIT_BGSAVE_START;
672672
c->reply = listCreate();

src/blocked.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,8 @@ void replyToBlockedClientTimedOut(client *c) {
221221

222222
/* Mass-unblock clients because something changed in the instance that makes
223223
* blocking no longer safe. For example clients blocked in list operations
224-
* in an instance which turns from master to slave is unsafe, so this function
225-
* is called when a master turns into a slave.
224+
* in an instance which turns from master to replica is unsafe, so this function
225+
* is called when a master turns into a replica.
226226
*
227227
* The semantics is to send an -UNBLOCKED error to the client, disconnecting
228228
* it at the same time. */

src/cluster.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ void clusterInit(void) {
499499
}
500500

501501
if (listenToPort(g_pserver->port+CLUSTER_PORT_INCR,
502-
g_pserver->cfd,&g_pserver->cfd_count, 0 /*fReusePort*/) == C_ERR)
502+
g_pserver->cfd,&g_pserver->cfd_count, 0 /*fReusePort*/, 0 /*fFirstListen*/) == C_ERR)
503503
{
504504
exit(1);
505505
} else {

src/config.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ configEnum aof_fsync_enum[] = {
9696
/* Output buffer limits presets. */
9797
clientBufferLimitsConfig clientBufferLimitsDefaults[CLIENT_TYPE_OBUF_COUNT] = {
9898
{0, 0, 0}, /* normal */
99-
{1024*1024*256, 1024*1024*64, 60}, /* slave */
99+
{1024*1024*256, 1024*1024*64, 60}, /* replica */
100100
{1024*1024*32, 1024*1024*8, 60} /* pubsub */
101101
};
102102

src/db.cpp

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ static robj *lookupKey(redisDb *db, robj *key, int flags) {
115115
* LOOKUP_NOTOUCH: don't alter the last access time of the key.
116116
*
117117
* Note: this function also returns NULL if the key is logically expired
118-
* but still existing, in case this is a slave, since this API is called only
118+
* but still existing, in case this is a replica, since this API is called only
119119
* for read operations. Even if the key expiry is master-driven, we can
120120
* correctly report a key is expired on slaves even if the master is lagging
121121
* expiring our key via DELs in the replication link. */
@@ -133,7 +133,7 @@ robj_roptr lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) {
133133
return NULL;
134134
}
135135

136-
/* However if we are in the context of a slave, expireIfNeeded() will
136+
/* However if we are in the context of a replica, expireIfNeeded() will
137137
* not really try to expire the key, it only returns information
138138
* about the "logical" status of the key: key expiring is up to the
139139
* master in order to have a consistent view of master's data set.
@@ -344,7 +344,7 @@ robj *dbRandomKey(redisDb *db) {
344344
if (allvolatile && listLength(g_pserver->masters) && --maxtries == 0) {
345345
/* If the DB is composed only of keys with an expire set,
346346
* it could happen that all the keys are already logically
347-
* expired in the slave, so the function cannot stop because
347+
* expired in the replica, so the function cannot stop because
348348
* expireIfNeeded() is false, nor it can stop because
349349
* dictGetRandomKey() returns NULL (there are keys to return).
350350
* To prevent the infinite loop we do some tries, but if there
@@ -1227,6 +1227,39 @@ int removeExpireCore(redisDb *db, robj *key, dictEntry *de) {
12271227
return 1;
12281228
}
12291229

1230+
int removeSubkeyExpire(redisDb *db, robj *key, robj *subkey) {
1231+
dictEntry *de = dictFind(db->pdict,ptrFromObj(key));
1232+
serverAssertWithInfo(NULL,key,de != NULL);
1233+
1234+
robj *val = (robj*)dictGetVal(de);
1235+
if (!val->FExpires())
1236+
return 0;
1237+
1238+
auto itr = db->setexpire->find((sds)dictGetKey(de));
1239+
serverAssert(itr != db->setexpire->end());
1240+
serverAssert(itr->key() == (sds)dictGetKey(de));
1241+
if (!itr->FFat())
1242+
return 0;
1243+
1244+
int found = 0;
1245+
for (auto subitr : *itr)
1246+
{
1247+
if (subitr.subkey() == nullptr)
1248+
continue;
1249+
if (sdscmp((sds)subitr.subkey(), szFromObj(subkey)) == 0)
1250+
{
1251+
itr->erase(subitr);
1252+
found = 1;
1253+
break;
1254+
}
1255+
}
1256+
1257+
if (itr->pfatentry()->size() == 0)
1258+
removeExpireCore(db, key, de);
1259+
1260+
return found;
1261+
}
1262+
12301263
/* Set an expire to the specified key. If the expire is set in the context
12311264
* of an user calling a command 'c' is the client, otherwise 'c' is set
12321265
* to NULL. The 'when' parameter is the absolute unix time in milliseconds
@@ -1335,7 +1368,7 @@ expireEntry *getExpire(redisDb *db, robj_roptr key) {
13351368
* to all the slaves and the AOF file if enabled.
13361369
*
13371370
* This way the key expiry is centralized in one place, and since both
1338-
* AOF and the master->slave link guarantee operation ordering, everything
1371+
* AOF and the master->replica link guarantee operation ordering, everything
13391372
* will be consistent even if we allow write operations against expiring
13401373
* keys. */
13411374
void propagateExpire(redisDb *db, robj *key, int lazy) {
@@ -1393,10 +1426,10 @@ int keyIsExpired(redisDb *db, robj *key) {
13931426
* is via lookupKey*() family of functions.
13941427
*
13951428
* The behavior of the function depends on the replication role of the
1396-
* instance, because slave instances do not expire keys, they wait
1429+
* instance, because replica instances do not expire keys, they wait
13971430
* for DELs from the master for consistency matters. However even
13981431
* slaves will try to have a coherent return value for the function,
1399-
* so that read commands executed in the slave side will be able to
1432+
* so that read commands executed in the replica side will be able to
14001433
* behave like if the key is expired even if still present (because the
14011434
* master has yet to propagate the DEL).
14021435
*
@@ -1409,9 +1442,9 @@ int keyIsExpired(redisDb *db, robj *key) {
14091442
int expireIfNeeded(redisDb *db, robj *key) {
14101443
if (!keyIsExpired(db,key)) return 0;
14111444

1412-
/* If we are running in the context of a slave, instead of
1445+
/* If we are running in the context of a replica, instead of
14131446
* evicting the expired key from the database, we return ASAP:
1414-
* the slave key expiration is controlled by the master that will
1447+
* the replica key expiration is controlled by the master that will
14151448
* send us synthesized DEL operations for expired keys.
14161449
*
14171450
* Still we try to return the right information to the caller,

src/evict.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,8 @@ size_t freeMemoryGetNotCountedMemory(void) {
374374

375375
listRewind(g_pserver->slaves,&li);
376376
while((ln = listNext(&li))) {
377-
client *slave = (client*)listNodeValue(ln);
378-
overhead += getClientOutputBufferMemoryUsage(slave);
377+
client *replica = (client*)listNodeValue(ln);
378+
overhead += getClientOutputBufferMemoryUsage(replica);
379379
}
380380
}
381381
if (g_pserver->aof_state != AOF_OFF) {

0 commit comments

Comments
 (0)