Compare commits
25
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5649473bd5 | ||
|
|
b4528b797d | ||
|
|
e070651039 | ||
|
|
7a32ec39fd | ||
|
|
50dfee2039 | ||
|
|
4b6bdcbcce | ||
|
|
31c0e38d86 | ||
|
|
8f5b94c75f | ||
|
|
d1fc7b96ed | ||
|
|
b253a7aa8d | ||
|
|
1625c74a36 | ||
|
|
3c716ee33d | ||
|
|
51216ee433 | ||
|
|
5f7ca6a2f6 | ||
|
|
889bcd1bf1 | ||
|
|
9637887264 | ||
|
|
07b1aaed74 | ||
|
|
97a6ff359e | ||
|
|
1e58b5bf0a | ||
|
|
8e65eab857 | ||
|
|
71729bac09 | ||
|
|
2789480e3d | ||
|
|
bbf7afd11d | ||
|
|
d7bd4f7a1c | ||
|
|
45bb6e801f |
No files matched your search
@@ -6,6 +6,7 @@ Build-Depends:
|
||||
debhelper (>= 9~),
|
||||
dpkg-dev (>= 1.17.5),
|
||||
systemd,
|
||||
libsystemd-dev <!nocheck>,
|
||||
procps <!nocheck>,
|
||||
build-essential <!nocheck>,
|
||||
tcl <!nocheck>,
|
||||
|
||||
@@ -1,16 +1,94 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Contact: John Sully <john@eqalpha.com>
|
||||
Upstream-Name: keydb-pro
|
||||
Source: https://github.com/JohnSully/KeyDB-Pro
|
||||
Upstream-Name: KeyDB
|
||||
Source: https://github.com/EQ-Alpha/KeyDB
|
||||
|
||||
Files: *
|
||||
Copyright: © 2006-2014 Salvatore Sanfilippo <antirez@gmail.com>
|
||||
Copyright © 2019, John Sully
|
||||
License: Proprietary
|
||||
Copyright:
|
||||
© 2006-2014 Salvatore Sanfilippo <antirez@gmail.com>
|
||||
© 2019-2021 John Sully
|
||||
© 2019-2021 EQ Alpha Technology Ltd.
|
||||
|
||||
License: BSD-3-clause
|
||||
|
||||
Files: debian/*
|
||||
Copyright: © 2009 Chris Lamb <lamby@debian.org>
|
||||
Files:
|
||||
src/rio.*
|
||||
src/t_zset.c
|
||||
src/ziplist.h
|
||||
src/intset.*
|
||||
src/redis-check-aof.c
|
||||
deps/hiredis/*
|
||||
deps/linenoise/*
|
||||
Copyright:
|
||||
© 2009-2012 Pieter Noordhuis <pcnoordhuis@gmail.com>
|
||||
© 2009-2012 Salvatore Sanfilippo <antirez@gmail.com>
|
||||
License: BSD-3-clause
|
||||
|
||||
Files:
|
||||
src/lzf.h
|
||||
src/lzfP.h
|
||||
src/lzf_d.c
|
||||
src/lzf_c.c
|
||||
Copyright:
|
||||
© 2000-2007 Marc Alexander Lehmann <schmorp@schmorp.de>
|
||||
© 2009-2012 Salvatore Sanfilippo <antirez@gmail.com>
|
||||
License: BSD-2-clause
|
||||
|
||||
Files: src/setproctitle.c
|
||||
Copyright:
|
||||
© 2010 William Ahern
|
||||
© 2013 Salvatore Sanfilippo
|
||||
© 2013 Stam He
|
||||
License: BSD-3-clause
|
||||
|
||||
Files: src/ae_evport.c
|
||||
Copyright: © 2012 Joyent, Inc.
|
||||
License: BSD-3-clause
|
||||
|
||||
Files: src/ae_kqueue.c
|
||||
Copyright: © 2009 Harish Mallipeddi <harish.mallipeddi@gmail.com>
|
||||
License: BSD-3-clause
|
||||
|
||||
Files: utils/install_server.sh
|
||||
Copyright: © 2011 Dvir Volk <dvirsk@gmail.com>
|
||||
License: BSD-3-clause
|
||||
|
||||
Files: deps/jemalloc/*
|
||||
Copyright:
|
||||
© 2002-2012 Jason Evans <jasone@canonware.com>
|
||||
© 2007-2012 Mozilla Foundation
|
||||
© 2009-2012 Facebook, Inc.
|
||||
License: BSD-3-clause
|
||||
|
||||
Files: src/pqsort.*
|
||||
Copyright: © 1992-1993 The Regents of the University of California
|
||||
License: BSD-3-clause
|
||||
|
||||
Files: deps/lua/*
|
||||
Copyright: © 1994-2012 Lua.org, PUC-Ri
|
||||
License: MIT
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
.
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
Files: pkg/deb/debian/*
|
||||
Copyright:
|
||||
© 2009 Chris Lamb <lamby@debian.org>
|
||||
© 2020-2021 EQ Alpha Technology Ltd. <support@eqalpha.com>
|
||||
License: BSD-3-clause
|
||||
|
||||
License: BSD-2-clause
|
||||
|
||||
@@ -5,3 +5,4 @@ src/keydb-check-rdb /usr/bin
|
||||
src/keydb-cli /usr/bin
|
||||
src/keydb-server /usr/bin
|
||||
src/keydb-sentinel /usr/bin
|
||||
src/keydb-diagnostic-tool /usr/bin
|
||||
@@ -3,6 +3,7 @@
|
||||
include /usr/share/dpkg/buildflags.mk
|
||||
|
||||
export BUILD_TLS=yes
|
||||
export USE_SYSTEMD=yes
|
||||
export CFLAGS CPPFLAGS LDFLAGS
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
export DEB_LDFLAGS_MAINT_APPEND = -ldl -latomic $(LUA_LDFLAGS)
|
||||
|
||||
@@ -6,6 +6,7 @@ Build-Depends:
|
||||
debhelper (>= 9~),
|
||||
dpkg-dev (>= 1.17.5),
|
||||
systemd,
|
||||
libsystemd-dev <!nocheck>,
|
||||
procps <!nocheck>,
|
||||
build-essential <!nocheck>,
|
||||
tcl <!nocheck>,
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Contact: John Sully <john@eqalpha.com>
|
||||
Upstream-Name: keydb
|
||||
Source: https://github.com/JohnSully/KeyDB
|
||||
Upstream-Name: KeyDB
|
||||
Source: https://github.com/EQ-Alpha/KeyDB
|
||||
|
||||
Files: *
|
||||
Copyright: © 2006-2014 Salvatore Sanfilippo <antirez@gmail.com>
|
||||
Copyright © 2019, John Sully
|
||||
Copyright:
|
||||
© 2006-2014 Salvatore Sanfilippo <antirez@gmail.com>
|
||||
© 2019-2021 John Sully
|
||||
© 2019-2021 EQ Alpha Technology Ltd.
|
||||
|
||||
License: BSD-3-clause
|
||||
|
||||
Files:
|
||||
@@ -82,8 +85,10 @@ License: MIT
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
Files: debian/*
|
||||
Copyright: © 2009 Chris Lamb <lamby@debian.org>
|
||||
Files: pkg/deb/debian_dh9/*
|
||||
Copyright:
|
||||
© 2009 Chris Lamb <lamby@debian.org>
|
||||
© 2020-2021 EQ Alpha Technology Ltd. <support@eqalpha.com>
|
||||
License: BSD-3-clause
|
||||
|
||||
License: BSD-2-clause
|
||||
|
||||
@@ -5,3 +5,4 @@ src/keydb-check-aof /usr/bin
|
||||
src/keydb-check-rdb /usr/bin
|
||||
src/keydb-cli /usr/bin
|
||||
src/keydb-sentinel /usr/bin
|
||||
src/keydb-diagnostic-tool /usr/bin
|
||||
@@ -9,6 +9,7 @@ include /usr/share/dpkg/buildflags.mk
|
||||
#LUA_LDFLAGS = $(addprefix -llua5.1-,$(LUA_LIBS_DEBIAN)) $(addprefix ../deps/lua/src/,$(LUA_OBJECTS))
|
||||
|
||||
export BUILD_TLS=yes
|
||||
export USE_SYSTEMD=yes
|
||||
export CFLAGS CPPFLAGS LDFLAGS
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
export DEB_LDFLAGS_MAINT_APPEND = -ldl -latomic $(LUA_LDFLAGS)
|
||||
|
||||
@@ -25,7 +25,13 @@ mkdir -p $DIR/keydb_build/keydb_rpm/var/log/keydb
|
||||
|
||||
# move binaries to bin
|
||||
rm $DIR/keydb_build/keydb_rpm/usr/bin/*
|
||||
cp $DIR/../../src/keydb-* $DIR/keydb_build/keydb_rpm/usr/bin/
|
||||
cp $DIR/../../src/keydb-server $DIR/keydb_build/keydb_rpm/usr/bin/
|
||||
cp $DIR/../../src/keydb-sentinel $DIR/keydb_build/keydb_rpm/usr/bin/
|
||||
cp $DIR/../../src/keydb-cli $DIR/keydb_build/keydb_rpm/usr/bin/
|
||||
cp $DIR/../../src/keydb-benchmark $DIR/keydb_build/keydb_rpm/usr/bin/
|
||||
cp $DIR/../../src/keydb-check-aof $DIR/keydb_build/keydb_rpm/usr/bin/
|
||||
cp $DIR/../../src/keydb-check-rdb $DIR/keydb_build/keydb_rpm/usr/bin/
|
||||
cp $DIR/../../src/keydb-diagnostic-tool $DIR/keydb_build/keydb_rpm/usr/bin/
|
||||
|
||||
# update spec file with build info
|
||||
sed -i '2d' $DIR/keydb_build/keydb.spec
|
||||
|
||||
+8
-2
@@ -223,12 +223,18 @@ uint64_t ACLGetCommandCategoryFlagByName(const char *name) {
|
||||
return 0; /* No match. */
|
||||
}
|
||||
|
||||
/* Method for passwords/pattern comparison used for the user->passwords list
|
||||
/* Method for pattern comparison used for the user->patterns list
|
||||
* so that we can search for items with listSearchKey(). */
|
||||
int ACLListMatchSds(void *a, void *b) {
|
||||
return sdscmp((sds)a,(sds)b) == 0;
|
||||
}
|
||||
|
||||
/* Method for password comparison used for the user->passwords list
|
||||
* Like the above, but uses a time independant compare for security reasons */
|
||||
int ACLListMatchSdsSecure(void *a, void* b) {
|
||||
return time_independent_strcmp((sds)a,(sds)b) == 0;
|
||||
}
|
||||
|
||||
/* Method to free list elements from ACL users password/patterns lists. */
|
||||
void ACLListFreeSds(const void *item) {
|
||||
sdsfree((sds)item);
|
||||
@@ -253,7 +259,7 @@ user *ACLCreateUser(const char *name, size_t namelen) {
|
||||
u->passwords = listCreate();
|
||||
u->patterns = listCreate();
|
||||
u->channels = listCreate();
|
||||
listSetMatchMethod(u->passwords,ACLListMatchSds);
|
||||
listSetMatchMethod(u->passwords,ACLListMatchSdsSecure);
|
||||
listSetFreeMethod(u->passwords,ACLListFreeSds);
|
||||
listSetDupMethod(u->passwords,ACLListDupSds);
|
||||
listSetMatchMethod(u->patterns,ACLListMatchSds);
|
||||
|
||||
+1
-1
@@ -879,7 +879,7 @@ int loadAppendOnlyFile(char *filename) {
|
||||
} else {
|
||||
/* RDB preamble. Pass loading the RDB functions. */
|
||||
rio rdb;
|
||||
rdbSaveInfo rsi = RDB_SAVE_INFO_INIT;
|
||||
rdbSaveInfo rsi;
|
||||
|
||||
serverLog(LL_NOTICE,"Reading RDB preamble from AOF file...");
|
||||
if (fseek(fp,0,SEEK_SET) == -1) goto readerr;
|
||||
|
||||
+16
-7
@@ -405,6 +405,10 @@ void printBits(unsigned char *p, unsigned long count) {
|
||||
#define BITFIELDOP_SET 1
|
||||
#define BITFIELDOP_INCRBY 2
|
||||
|
||||
/* Make sure we don't bit shift too many bits at a time.
|
||||
* Even this amount is probably way too large. */
|
||||
#define BITOP_SHIFT_MAX (1<<30)
|
||||
|
||||
/* This helper function used by GETBIT / SETBIT parses the bit offset argument
|
||||
* making sure an error is returned if it is negative or if it overflows
|
||||
* Redis 512 MB limit for the string value or more (server.proto_max_bulk_len).
|
||||
@@ -642,6 +646,11 @@ void bitopCommand(client *c) {
|
||||
addReplyError(c, "BITOP SHIFT's last parameter must be an integer");
|
||||
return;
|
||||
}
|
||||
if (shift > BITOP_SHIFT_MAX) {
|
||||
addReplyError(c, "BITOP SHIFT value is too large.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (op == BITOP_RSHIFT)
|
||||
shift = -shift;
|
||||
}
|
||||
@@ -682,7 +691,7 @@ void bitopCommand(client *c) {
|
||||
|
||||
if (fShiftOp)
|
||||
{
|
||||
long newlen = (long)maxlen + shift/CHAR_BIT;
|
||||
long long newlen = (long long)maxlen + shift/CHAR_BIT;
|
||||
if (shift > 0 && (shift % CHAR_BIT) != 0)
|
||||
newlen++;
|
||||
|
||||
@@ -694,14 +703,14 @@ void bitopCommand(client *c) {
|
||||
res = (unsigned char*) sdsnewlen(NULL,newlen);
|
||||
if (shift >= 0)
|
||||
{ // left shift
|
||||
long byteoffset = shift/CHAR_BIT;
|
||||
long long byteoffset = shift/CHAR_BIT;
|
||||
memset(res, 0, byteoffset);
|
||||
long srcLen = newlen - byteoffset - ((shift % CHAR_BIT) ? 1 : 0);
|
||||
long long srcLen = newlen - byteoffset - ((shift % CHAR_BIT) ? 1 : 0);
|
||||
|
||||
// now the bitshift+copy
|
||||
unsigned bitshift = shift % CHAR_BIT;
|
||||
unsigned char carry = 0;
|
||||
for (long iSrc = 0; iSrc < srcLen; ++iSrc)
|
||||
for (long long iSrc = 0; iSrc < srcLen; ++iSrc)
|
||||
{
|
||||
res[byteoffset+iSrc] = (src[0][iSrc] << bitshift) | carry;
|
||||
carry = src[0][iSrc] >> (CHAR_BIT - bitshift);
|
||||
@@ -711,14 +720,14 @@ void bitopCommand(client *c) {
|
||||
}
|
||||
else
|
||||
{ // right shift
|
||||
long byteoffset = -shift/CHAR_BIT;
|
||||
long long byteoffset = -shift/CHAR_BIT;
|
||||
unsigned bitshift = -shift % CHAR_BIT;
|
||||
if (bitshift)
|
||||
++byteoffset;
|
||||
res[0] = (src[0][byteoffset] << (CHAR_BIT-bitshift));
|
||||
if (byteoffset > 0)
|
||||
res[0] |= (src[0][byteoffset-1] >> bitshift);
|
||||
for (long idx = 1; idx < newlen; ++idx)
|
||||
for (long long idx = 1; idx < newlen; ++idx)
|
||||
{
|
||||
res[idx] = (src[0][byteoffset+idx] << (CHAR_BIT-bitshift)) | (src[0][byteoffset+idx-1] >> bitshift);
|
||||
}
|
||||
@@ -800,8 +809,8 @@ void bitopCommand(client *c) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* j is set to the next byte to process by the previous loop. */
|
||||
for (; j < maxlen; j++) {
|
||||
|
||||
@@ -51,6 +51,7 @@ void cronCommand(client *c)
|
||||
|
||||
if (c->argc < (6 + numkeys)) {
|
||||
addReplyError(c, "Missing arguments or numkeys is too big");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4289,7 +4289,14 @@ RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const ch
|
||||
if (!(flags & REDISMODULE_ARGV_NO_REPLICAS))
|
||||
call_flags |= CMD_CALL_PROPAGATE_REPL;
|
||||
}
|
||||
|
||||
{
|
||||
aeAcquireLock();
|
||||
std::unique_lock<fastlock> ul(c->lock);
|
||||
call(c,call_flags);
|
||||
aeReleaseLock();
|
||||
}
|
||||
|
||||
g_pserver->replication_allowed = prev_replication_allowed;
|
||||
|
||||
serverAssert((c->flags & CLIENT_BLOCKED) == 0);
|
||||
|
||||
+4
-4
@@ -1324,8 +1324,7 @@ void acceptOnThread(connection *conn, int flags, char *cip)
|
||||
int res = aePostFunction(g_pserver->rgthreadvar[ielTarget].el, [conn, flags, ielTarget, szT, fBootLoad] {
|
||||
connMarshalThread(conn);
|
||||
acceptCommonHandler(conn,flags,szT,ielTarget);
|
||||
if (!g_fTestMode && !fBootLoad)
|
||||
rgacceptsInFlight[ielTarget].fetch_sub(1, std::memory_order_relaxed);
|
||||
rgacceptsInFlight[ielTarget].fetch_sub(1, std::memory_order_relaxed);
|
||||
zfree(szT);
|
||||
});
|
||||
|
||||
@@ -1333,8 +1332,7 @@ void acceptOnThread(connection *conn, int flags, char *cip)
|
||||
return;
|
||||
// If res != AE_OK we can still try to accept on the local thread
|
||||
}
|
||||
if (!g_fTestMode && !fBootLoad)
|
||||
rgacceptsInFlight[ielTarget].fetch_sub(1, std::memory_order_relaxed);
|
||||
rgacceptsInFlight[ielTarget].fetch_sub(1, std::memory_order_relaxed);
|
||||
|
||||
aeAcquireLock();
|
||||
acceptCommonHandler(conn,flags,cip,ielCur);
|
||||
@@ -1944,7 +1942,9 @@ void ProcessPendingAsyncWrites()
|
||||
bool fResult = c->postFunction([](client *c) {
|
||||
c->fPendingAsyncWriteHandler = false;
|
||||
clientInstallWriteHandler(c);
|
||||
c->lock.unlock();
|
||||
handleClientsWithPendingWrites(c->iel, g_pserver->aof_state);
|
||||
c->lock.lock();
|
||||
}, false);
|
||||
|
||||
if (!fResult)
|
||||
|
||||
+5
-2
@@ -27,14 +27,17 @@ void *operator new(std::size_t size, const std::nothrow_t &) noexcept
|
||||
return zmalloc(size, MALLOC_LOCAL);
|
||||
}
|
||||
|
||||
//need to do null checks for delete since the compiler can optimize out null checks in zfree
|
||||
void operator delete(void * p) noexcept
|
||||
{
|
||||
zfree(p);
|
||||
if (p != nullptr)
|
||||
zfree(p);
|
||||
}
|
||||
|
||||
void operator delete(void *p, std::size_t) noexcept
|
||||
{
|
||||
zfree(p);
|
||||
if (p != nullptr)
|
||||
zfree(p);
|
||||
}
|
||||
|
||||
#endif
|
||||
+55
-4
@@ -1205,6 +1205,40 @@ int rdbSaveInfoAuxFields(rio *rdb, int rdbflags, rdbSaveInfo *rsi) {
|
||||
== -1) return -1;
|
||||
if (rdbSaveAuxFieldStrInt(rdb,"repl-offset",g_pserver->master_repl_offset)
|
||||
== -1) return -1;
|
||||
if (g_pserver->fActiveReplica && listLength(g_pserver->masters) > 0) {
|
||||
sdsstring val = sdsstring(sdsempty());
|
||||
listNode *ln;
|
||||
listIter li;
|
||||
redisMaster* mi;
|
||||
listRewind(g_pserver->masters,&li);
|
||||
while ((ln = listNext(&li)) != NULL) {
|
||||
mi = (redisMaster*)listNodeValue(ln);
|
||||
if (!mi->master) {
|
||||
// If master client is not available, use info from master struct - better than nothing
|
||||
serverLog(LL_NOTICE, "saving master %s", mi->master_replid);
|
||||
if (mi->master_replid[0] == 0) {
|
||||
// if replid is null, there's no reason to save it
|
||||
continue;
|
||||
}
|
||||
val = val.catfmt("%s:%I:%s:%i;", mi->master_replid,
|
||||
mi->master_initial_offset,
|
||||
mi->masterhost,
|
||||
mi->masterport);
|
||||
}
|
||||
else {
|
||||
serverLog(LL_NOTICE, "saving master %s", mi->master->replid);
|
||||
if (mi->master->replid[0] == 0) {
|
||||
// if replid is null, there's no reason to save it
|
||||
continue;
|
||||
}
|
||||
val = val.catfmt("%s:%I:%s:%i;", mi->master->replid,
|
||||
mi->master->reploff,
|
||||
mi->masterhost,
|
||||
mi->masterport);
|
||||
}
|
||||
}
|
||||
if (rdbSaveAuxFieldStrStr(rdb, "repl-masters",val.get()) == -1) return -1;
|
||||
}
|
||||
}
|
||||
if (rdbSaveAuxFieldStrInt(rdb,"aof-preamble",aof_preamble) == -1) return -1;
|
||||
return 1;
|
||||
@@ -2653,6 +2687,23 @@ int rdbLoadRio(rio *rdb, int rdbflags, rdbSaveInfo *rsi) {
|
||||
memcpy(rsi->repl_id,ptrFromObj(auxval),CONFIG_RUN_ID_SIZE+1);
|
||||
rsi->repl_id_is_set = 1;
|
||||
}
|
||||
} else if (!strcasecmp(szFromObj(auxkey),"repl-masters")) {
|
||||
if (rsi) {
|
||||
struct redisMaster mi;
|
||||
char *masters = szFromObj(auxval);
|
||||
char *entry = strtok(masters, ":");
|
||||
while (entry != NULL) {
|
||||
memcpy(mi.master_replid, entry, sizeof(mi.master_replid));
|
||||
entry = strtok(NULL, ":");
|
||||
mi.master_initial_offset = atoi(entry);
|
||||
entry = strtok(NULL, ":");
|
||||
mi.masterhost = entry;
|
||||
entry = strtok(NULL, ";");
|
||||
mi.masterport = atoi(entry);
|
||||
entry = strtok(NULL, ":");
|
||||
rsi->addMaster(mi);
|
||||
}
|
||||
}
|
||||
} else if (!strcasecmp(szFromObj(auxkey),"repl-offset")) {
|
||||
if (rsi) rsi->repl_offset = strtoll(szFromObj(auxval),NULL,10);
|
||||
} else if (!strcasecmp(szFromObj(auxkey),"lua")) {
|
||||
@@ -2817,11 +2868,11 @@ int rdbLoadRio(rio *rdb, int rdbflags, rdbSaveInfo *rsi) {
|
||||
bool fExpiredKey = iAmMaster() && !(rdbflags&RDBFLAGS_AOF_PREAMBLE) && expiretime != -1 && expiretime < now;
|
||||
|
||||
if (fStaleMvccKey || fExpiredKey) {
|
||||
if (fStaleMvccKey && !fExpiredKey && rsi != nullptr && rsi->mi != nullptr && rsi->mi->staleKeyMap != nullptr && lookupKeyRead(db, &keyobj) == nullptr) {
|
||||
if (fStaleMvccKey && !fExpiredKey && rsi != nullptr && rsi->masters != nullptr && rsi->masters[0].staleKeyMap != nullptr && lookupKeyRead(db, &keyobj) == nullptr) {
|
||||
// We have a key that we've already deleted and is not back in our database.
|
||||
// We'll need to inform the sending master of the delete if it is also a replica of us
|
||||
robj_sharedptr objKeyDup(createStringObject(key, sdslen(key)));
|
||||
rsi->mi->staleKeyMap->operator[](db - g_pserver->db).push_back(objKeyDup);
|
||||
rsi->masters[0].staleKeyMap->operator[](db - g_pserver->db).push_back(objKeyDup);
|
||||
}
|
||||
fLastKeyExpired = true;
|
||||
sdsfree(key);
|
||||
@@ -3246,8 +3297,8 @@ void bgsaveCommand(client *c) {
|
||||
* is returned, and the RDB saving will not persist any replication related
|
||||
* information. */
|
||||
rdbSaveInfo *rdbPopulateSaveInfo(rdbSaveInfo *rsi) {
|
||||
rdbSaveInfo rsi_init = RDB_SAVE_INFO_INIT;
|
||||
*rsi = rsi_init;
|
||||
rdbSaveInfo rsi_init;
|
||||
*rsi = std::move(rsi_init);
|
||||
|
||||
/* If the instance is a master, we can populate the replication info
|
||||
* only when repl_backlog is not NULL. If the repl_backlog is NULL,
|
||||
|
||||
@@ -1984,7 +1984,6 @@ int main(int argc, const char **argv) {
|
||||
} while(config.loop);
|
||||
zfree(data);
|
||||
|
||||
zfree(data);
|
||||
if (config.redis_config != NULL) freeRedisConfig(config.redis_config);
|
||||
|
||||
return 0;
|
||||
|
||||
+31
-22
@@ -1987,7 +1987,7 @@ void readSyncBulkPayload(connection *conn) {
|
||||
ssize_t nread, readlen, nwritten;
|
||||
int use_diskless_load = useDisklessLoad();
|
||||
dbBackup *diskless_load_backup = NULL;
|
||||
rdbSaveInfo rsi = RDB_SAVE_INFO_INIT;
|
||||
rdbSaveInfo rsi;
|
||||
int empty_db_flags = g_pserver->repl_slave_lazy_flush ? EMPTYDB_ASYNC :
|
||||
EMPTYDB_NO_FLAGS;
|
||||
off_t left;
|
||||
@@ -2308,7 +2308,7 @@ void readSyncBulkPayload(connection *conn) {
|
||||
mi->staleKeyMap->clear();
|
||||
else
|
||||
mi->staleKeyMap = new (MALLOC_LOCAL) std::map<int, std::vector<robj_sharedptr>>();
|
||||
rsi.mi = mi;
|
||||
rsi.addMaster(*mi);
|
||||
}
|
||||
if (rdbLoadFile(rdb_filename,&rsi,RDBFLAGS_REPLICATION) != C_OK) {
|
||||
serverLog(LL_WARNING,
|
||||
@@ -2359,7 +2359,7 @@ void readSyncBulkPayload(connection *conn) {
|
||||
{
|
||||
mergeReplicationId(mi->master->replid);
|
||||
}
|
||||
else
|
||||
else if (!g_pserver->fActiveReplica)
|
||||
{
|
||||
/* After a full resynchroniziation we use the replication ID and
|
||||
* offset of the master. The secondary ID / offset are cleared since
|
||||
@@ -2555,7 +2555,7 @@ int slaveTryPartialResynchronization(redisMaster *mi, connection *conn, int read
|
||||
* client structure representing the master into g_pserver->master. */
|
||||
mi->master_initial_offset = -1;
|
||||
|
||||
if (mi->cached_master && !g_pserver->fActiveReplica) {
|
||||
if (mi->cached_master) {
|
||||
psync_replid = mi->cached_master->replid;
|
||||
snprintf(psync_offset,sizeof(psync_offset),"%lld", mi->cached_master->reploff+1);
|
||||
serverLog(LL_NOTICE,"Trying a partial resynchronization (request %s:%s).", psync_replid, psync_offset);
|
||||
@@ -2654,14 +2654,15 @@ int slaveTryPartialResynchronization(redisMaster *mi, connection *conn, int read
|
||||
sizeof(g_pserver->replid2));
|
||||
g_pserver->second_replid_offset = g_pserver->master_repl_offset+1;
|
||||
|
||||
/* Update the cached master ID and our own primary ID to the
|
||||
* new one. */
|
||||
memcpy(g_pserver->replid,sznew,sizeof(g_pserver->replid));
|
||||
memcpy(mi->cached_master->replid,sznew,sizeof(g_pserver->replid));
|
||||
if (!g_pserver->fActiveReplica) {
|
||||
/* Update the cached master ID and our own primary ID to the
|
||||
* new one. */
|
||||
memcpy(g_pserver->replid,sznew,sizeof(g_pserver->replid));
|
||||
memcpy(mi->cached_master->replid,sznew,sizeof(g_pserver->replid));
|
||||
|
||||
/* Disconnect all the sub-slaves: they need to be notified. */
|
||||
if (!g_pserver->fActiveReplica)
|
||||
/* Disconnect all the sub-slaves: they need to be notified. */
|
||||
disconnectSlaves();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3022,18 +3023,6 @@ retry_connect:
|
||||
disconnectSlavesExcept(mi->master_uuid); /* Force our slaves to resync with us as well. */
|
||||
freeReplicationBacklog(); /* Don't allow our chained slaves to PSYNC. */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (listLength(g_pserver->slaves))
|
||||
{
|
||||
changeReplicationId();
|
||||
clearReplicationId2();
|
||||
}
|
||||
else
|
||||
{
|
||||
freeReplicationBacklog(); /* Don't allow our chained slaves to PSYNC. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Fall back to SYNC if needed. Otherwise psync_result == PSYNC_FULLRESYNC
|
||||
* and the g_pserver->master_replid and master_initial_offset are
|
||||
@@ -3679,6 +3668,26 @@ void replicationCacheMasterUsingMyself(redisMaster *mi) {
|
||||
mi->master = NULL;
|
||||
}
|
||||
|
||||
/* This function is called when reloading master info from an RDB in Active Replica mode.
|
||||
* It creates a cached master client using the info contained in the redisMaster struct.
|
||||
*
|
||||
* Assumes that the passed struct contains valid master info. */
|
||||
void replicationCacheMasterUsingMaster(redisMaster *mi) {
|
||||
if (mi->cached_master) {
|
||||
freeClient(mi->cached_master);
|
||||
}
|
||||
|
||||
replicationCreateMasterClient(mi, NULL, -1);
|
||||
std::lock_guard<decltype(mi->master->lock)> lock(mi->master->lock);
|
||||
|
||||
memcpy(mi->master->replid, mi->master_replid, sizeof(mi->master_replid));
|
||||
mi->master->reploff = mi->master_initial_offset;
|
||||
|
||||
unlinkClient(mi->master);
|
||||
mi->cached_master = mi->master;
|
||||
mi->master = NULL;
|
||||
}
|
||||
|
||||
/* Free a cached master, called when there are no longer the conditions for
|
||||
* a partial resync on reconnection. */
|
||||
void replicationDiscardCachedMaster(redisMaster *mi) {
|
||||
|
||||
@@ -424,6 +424,21 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
sdsstring &operator=(sdsstring &&other)
|
||||
{
|
||||
sds tmp = m_str;
|
||||
m_str = other.m_str;
|
||||
other.m_str = tmp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
sdsstring catfmt(const char *fmt, Args... args)
|
||||
{
|
||||
m_str = sdscatfmt(m_str, fmt, args...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
sds release() {
|
||||
sds sdsT = m_str;
|
||||
m_str = nullptr;
|
||||
|
||||
+23
-7
@@ -6300,7 +6300,7 @@ void loadDataFromDisk(void) {
|
||||
if (loadAppendOnlyFile(g_pserver->aof_filename) == C_OK)
|
||||
serverLog(LL_NOTICE,"DB loaded from append only file: %.3f seconds",(float)(ustime()-start)/1000000);
|
||||
} else if (g_pserver->rdb_filename != NULL || g_pserver->rdb_s3bucketpath != NULL) {
|
||||
rdbSaveInfo rsi = RDB_SAVE_INFO_INIT;
|
||||
rdbSaveInfo rsi;
|
||||
errno = 0; /* Prevent a stale value from affecting error checking */
|
||||
if (rdbLoad(&rsi,RDBFLAGS_NONE) == C_OK) {
|
||||
serverLog(LL_NOTICE,"DB loaded from disk: %.3f seconds",
|
||||
@@ -6328,11 +6328,23 @@ void loadDataFromDisk(void) {
|
||||
while ((ln = listNext(&li)))
|
||||
{
|
||||
redisMaster *mi = (redisMaster*)listNodeValue(ln);
|
||||
/* If we are a replica, create a cached master from this
|
||||
* information, in order to allow partial resynchronizations
|
||||
* with masters. */
|
||||
replicationCacheMasterUsingMyself(mi);
|
||||
selectDb(mi->cached_master,rsi.repl_stream_db);
|
||||
if (g_pserver->fActiveReplica) {
|
||||
for (size_t i = 0; i < rsi.numMasters(); i++) {
|
||||
if (!strcmp(mi->masterhost, rsi.masters[i].masterhost) && mi->masterport == rsi.masters[i].masterport) {
|
||||
memcpy(mi->master_replid, rsi.masters[i].master_replid, sizeof(mi->master_replid));
|
||||
mi->master_initial_offset = rsi.masters[i].master_initial_offset;
|
||||
replicationCacheMasterUsingMaster(mi);
|
||||
serverLog(LL_NOTICE, "Cached master recovered from RDB for %s:%d", mi->masterhost, mi->masterport);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* If we are a replica, create a cached master from this
|
||||
* information, in order to allow partial resynchronizations
|
||||
* with masters. */
|
||||
replicationCacheMasterUsingMyself(mi);
|
||||
selectDb(mi->cached_master,rsi.repl_stream_db);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (errno != ENOENT) {
|
||||
@@ -6562,7 +6574,11 @@ void *timeThreadMain(void*) {
|
||||
}
|
||||
}
|
||||
updateCachedTime();
|
||||
#if defined(__APPLE__)
|
||||
nanosleep(&delay, nullptr);
|
||||
#else
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &delay, NULL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6898,7 +6914,7 @@ int main(int argc, char **argv) {
|
||||
__AFL_INIT();
|
||||
#endif
|
||||
rio rdb;
|
||||
rdbSaveInfo rsi = RDB_SAVE_INFO_INIT;
|
||||
rdbSaveInfo rsi;
|
||||
startLoadingFile(stdin, (char*)"stdin", 0);
|
||||
rioInitWithFile(&rdb,stdin);
|
||||
rdbLoadRio(&rdb,0,&rsi);
|
||||
|
||||
+97
-36
@@ -1389,6 +1389,38 @@ struct redisMemOverhead {
|
||||
} *db;
|
||||
};
|
||||
|
||||
struct redisMaster {
|
||||
char *masteruser; /* AUTH with this user and masterauth with master */
|
||||
char *masterauth; /* AUTH with this password with master */
|
||||
char *masterhost; /* Hostname of master */
|
||||
int masterport; /* Port of master */
|
||||
client *cached_master; /* Cached master to be reused for PSYNC. */
|
||||
client *master;
|
||||
/* 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. */
|
||||
char master_replid[CONFIG_RUN_ID_SIZE+1]; /* Master PSYNC runid. */
|
||||
long long master_initial_offset; /* Master PSYNC offset. */
|
||||
|
||||
bool isActive = false;
|
||||
int repl_state; /* Replication status if the instance is a replica */
|
||||
off_t repl_transfer_size; /* Size of RDB to read from master during sync. */
|
||||
off_t repl_transfer_read; /* Amount of RDB read from master during sync. */
|
||||
off_t repl_transfer_last_fsync_off; /* Offset when we fsync-ed last time. */
|
||||
connection *repl_transfer_s; /* Slave -> Master SYNC socket */
|
||||
int repl_transfer_fd; /* Slave -> Master SYNC temp file descriptor */
|
||||
char *repl_transfer_tmpfile; /* Slave-> master SYNC temp file name */
|
||||
time_t repl_transfer_lastio; /* Unix time of the latest read, for timeout */
|
||||
time_t repl_down_since; /* Unix time at which link with master went down */
|
||||
|
||||
unsigned char master_uuid[UUID_BINARY_LEN]; /* Used during sync with master, this is our master's UUID */
|
||||
/* After we've connected with our master use the UUID in g_pserver->master */
|
||||
uint64_t mvccLastSync;
|
||||
/* During a handshake the server may have stale keys, we track these here to share once a reciprocal connection is made */
|
||||
std::map<int, std::vector<robj_sharedptr>> *staleKeyMap;
|
||||
int ielReplTransfer = -1;
|
||||
};
|
||||
|
||||
/* This structure can be optionally passed to RDB save/load functions in
|
||||
* order to implement additional functionalities, by storing and loading
|
||||
* metadata to the RDB file.
|
||||
@@ -1397,7 +1429,66 @@ struct redisMemOverhead {
|
||||
* replication in order to make sure that chained slaves (slaves of slaves)
|
||||
* select the correct DB and are able to accept the stream coming from the
|
||||
* top-level master. */
|
||||
typedef struct rdbSaveInfo {
|
||||
class rdbSaveInfo {
|
||||
public:
|
||||
rdbSaveInfo() {
|
||||
repl_stream_db = -1;
|
||||
repl_id_is_set = 0;
|
||||
memcpy(repl_id, "0000000000000000000000000000000000000000", sizeof(repl_id));
|
||||
repl_offset = -1;
|
||||
fForceSetKey = TRUE;
|
||||
mvccMinThreshold = 0;
|
||||
masters = nullptr;
|
||||
masterCount = 0;
|
||||
}
|
||||
rdbSaveInfo(const rdbSaveInfo &other) {
|
||||
repl_stream_db = other.repl_stream_db;
|
||||
repl_id_is_set = other.repl_id_is_set;
|
||||
memcpy(repl_id, other.repl_id, sizeof(repl_id));
|
||||
repl_offset = other.repl_offset;
|
||||
fForceSetKey = other.fForceSetKey;
|
||||
mvccMinThreshold = other.mvccMinThreshold;
|
||||
masters = (struct redisMaster*)malloc(sizeof(struct redisMaster) * other.masterCount);
|
||||
memcpy(masters, other.masters, sizeof(struct redisMaster) * other.masterCount);
|
||||
masterCount = other.masterCount;
|
||||
}
|
||||
rdbSaveInfo(rdbSaveInfo &&other) : rdbSaveInfo() {
|
||||
swap(*this, other);
|
||||
}
|
||||
rdbSaveInfo &operator=(rdbSaveInfo other) {
|
||||
swap(*this, other);
|
||||
return *this;
|
||||
}
|
||||
~rdbSaveInfo() {
|
||||
free(masters);
|
||||
}
|
||||
friend void swap(rdbSaveInfo &first, rdbSaveInfo &second) {
|
||||
std::swap(first.repl_stream_db, second.repl_stream_db);
|
||||
std::swap(first.repl_id_is_set, second.repl_id_is_set);
|
||||
std::swap(first.repl_id, second.repl_id);
|
||||
std::swap(first.repl_offset, second.repl_offset);
|
||||
std::swap(first.fForceSetKey, second.fForceSetKey);
|
||||
std::swap(first.mvccMinThreshold, second.mvccMinThreshold);
|
||||
std::swap(first.masters, second.masters);
|
||||
std::swap(first.masterCount, second.masterCount);
|
||||
|
||||
}
|
||||
|
||||
void addMaster(const struct redisMaster &mi) {
|
||||
masterCount++;
|
||||
if (masters == nullptr) {
|
||||
masters = (struct redisMaster*)malloc(sizeof(struct redisMaster));
|
||||
}
|
||||
else {
|
||||
masters = (struct redisMaster*)realloc(masters, sizeof(struct redisMaster) * masterCount);
|
||||
}
|
||||
memcpy(masters + masterCount - 1, &mi, sizeof(struct redisMaster));
|
||||
}
|
||||
|
||||
size_t numMasters() {
|
||||
return masterCount;
|
||||
}
|
||||
|
||||
/* Used saving and loading. */
|
||||
int repl_stream_db; /* DB to select in g_pserver->master client. */
|
||||
|
||||
@@ -1407,10 +1498,11 @@ typedef struct rdbSaveInfo {
|
||||
long long repl_offset; /* Replication offset. */
|
||||
int fForceSetKey;
|
||||
uint64_t mvccMinThreshold;
|
||||
struct redisMaster *mi;
|
||||
} rdbSaveInfo;
|
||||
struct redisMaster *masters;
|
||||
|
||||
#define RDB_SAVE_INFO_INIT {-1,0,"0000000000000000000000000000000000000000",-1, TRUE, 0, nullptr}
|
||||
private:
|
||||
size_t masterCount;
|
||||
};
|
||||
|
||||
struct malloc_stats {
|
||||
size_t zmalloc_used;
|
||||
@@ -1499,38 +1591,6 @@ struct redisServerThreadVars {
|
||||
std::vector<client*> vecclientsProcess;
|
||||
};
|
||||
|
||||
struct redisMaster {
|
||||
char *masteruser; /* AUTH with this user and masterauth with master */
|
||||
char *masterauth; /* AUTH with this password with master */
|
||||
char *masterhost; /* Hostname of master */
|
||||
int masterport; /* Port of master */
|
||||
client *cached_master; /* Cached master to be reused for PSYNC. */
|
||||
client *master;
|
||||
/* 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. */
|
||||
char master_replid[CONFIG_RUN_ID_SIZE+1]; /* Master PSYNC runid. */
|
||||
long long master_initial_offset; /* Master PSYNC offset. */
|
||||
|
||||
bool isActive = false;
|
||||
int repl_state; /* Replication status if the instance is a replica */
|
||||
off_t repl_transfer_size; /* Size of RDB to read from master during sync. */
|
||||
off_t repl_transfer_read; /* Amount of RDB read from master during sync. */
|
||||
off_t repl_transfer_last_fsync_off; /* Offset when we fsync-ed last time. */
|
||||
connection *repl_transfer_s; /* Slave -> Master SYNC socket */
|
||||
int repl_transfer_fd; /* Slave -> Master SYNC temp file descriptor */
|
||||
char *repl_transfer_tmpfile; /* Slave-> master SYNC temp file name */
|
||||
time_t repl_transfer_lastio; /* Unix time of the latest read, for timeout */
|
||||
time_t repl_down_since; /* Unix time at which link with master went down */
|
||||
|
||||
unsigned char master_uuid[UUID_BINARY_LEN]; /* Used during sync with master, this is our master's UUID */
|
||||
/* After we've connected with our master use the UUID in g_pserver->master */
|
||||
uint64_t mvccLastSync;
|
||||
/* During a handshake the server may have stale keys, we track these here to share once a reciprocal connection is made */
|
||||
std::map<int, std::vector<robj_sharedptr>> *staleKeyMap;
|
||||
int ielReplTransfer = -1;
|
||||
};
|
||||
|
||||
// Const vars are not changed after worker threads are launched
|
||||
struct redisServerConst {
|
||||
pid_t pid; /* Main process pid. */
|
||||
@@ -2441,6 +2501,7 @@ void clearReplicationId2(void);
|
||||
void mergeReplicationId(const char *);
|
||||
void chopReplicationBacklog(void);
|
||||
void replicationCacheMasterUsingMyself(struct redisMaster *mi);
|
||||
void replicationCacheMasterUsingMaster(struct redisMaster *mi);
|
||||
void feedReplicationBacklog(const void *ptr, size_t len);
|
||||
void updateMasterAuth();
|
||||
void showLatestBacklog();
|
||||
|
||||
Reference in new issue
Block a user