Compare commits

..
Author SHA1 Message Date
Malavan Sotheeswaran 717805e191 init iteration 2023-08-22 22:48:26 -07:00
Malavan Sotheeswaran 8f8b61f211 compile fix 2023-08-22 13:18:14 -07:00
Malavan Sotheeswaran fca3c77823 somehow missed reference to m_setexpire 2023-08-22 13:03:03 -07:00
Malavan Sotheeswaran 22a0ad9a23 Merge remote-tracking branch 'internal/main' into flash_expiration 2023-08-22 12:48:28 -07:00
Zhaozhen Liang c97f696ea2 Merge pull request #219 from Snapchat/emit-non-empty-shard-less-replica-issue
add metric emit for non-empty primary with less than 2 connected replicas
2023-08-22 11:34:09 -06:00
zliang cec570fdf1 address comments 2023-08-22 11:10:56 -06:00
zliang 6375e919b9 add metric emit for non-empty primary with less than 2 connected replicas 2023-08-21 18:29:05 -06:00
Zhaozhen Liang bf29926686 Merge pull request #218 from Snapchat/change-memfree-to-memavailable
update MemFree to MemAvailable in keydb statsd
2023-08-21 16:46:38 -06:00
zliang 813bf15ae0 update MemFree to MemAvailable in keydb statsd 2023-08-21 15:28:26 -06:00
John Sully ffac55273a Remove Expireset (#217)
Major refactor to place expiry information directly in the object struct.
2023-08-21 16:36:45 -04:00
Zhaozhen Liang 80dcbad30f Merge pull request #216 from Snapchat/add-free-memory-and-shard-num-metrics-emit-statsd
emit system free memory metrics with '/proc/meminfo'
2023-08-18 10:50:21 -06:00
zliang eb14f4298c have emit system free memory within metrics_time_taken_us and also add metric time taken for it 2023-08-18 10:20:00 -06:00
zliang 6fa696bb98 emit system free metrics with '/proc/meminfo' 2023-08-17 19:31:52 -06:00
Zhaozhen Liang abd6e77c95 Merge pull request #215 from Snapchat/make-docker-build-independent
make docker build independent
2023-08-16 12:24:25 -06:00
zliang 7a00a43170 add new build to ci 2023-08-15 15:52:59 -06:00
zliang 426eabe143 make docker build independent 2023-08-15 15:27:05 -06:00
Zhaozhen Liang 222776e98b Merge pull request #214 from Snapchat/update-docker-build-tag
use commit hash as tag template
2023-08-15 13:13:30 -06:00
zliang 76fec1c22e Revert "test tag"
This reverts commit 9cbc57137d.
2023-08-15 12:40:10 -06:00
zliang 9cbc57137d test tag 2023-08-15 12:25:15 -06:00
zliang 94b40af1c3 fix 2023-08-15 11:56:03 -06:00
zliang df9039d83f use commit hash as tag template 2023-08-15 11:37:29 -06:00
Zhaozhen Liang a1b55eddf8 Merge pull request #211 from Snapchat/machamp-release-publish-image
add docker build
2023-08-15 09:40:43 -06:00
zliang 70f2a74ff1 fix the comment caused stuck docker build 2023-08-14 18:34:05 -06:00
zliang e15a2b609c fix 2023-08-14 17:05:37 -06:00
zliang 7d96689ae6 fix check in Dockerfile docker-entrypoint.sh 2023-08-14 16:31:41 -06:00
Zhaozhen Liang 8cbb53e7cb Merge branch 'main' into machamp-release-publish-image 2023-08-14 12:55:30 -06:00
zliang b6f91e4c26 include building keydb statsd module 2023-08-14 12:03:36 -06:00
Zhaozhen Liang deb48fba62 Merge pull request #213 from Snapchat/move-cpp-statsd-client-to-dep
move cpp-statsd-client to deps
2023-08-14 11:30:40 -06:00
zliang b51f267112 remove submodule instead use the source 2023-08-14 11:13:06 -06:00
zliang a055da3b4c update relative path in compilation 2023-08-14 10:56:51 -06:00
zliang 68ce12ad3a checkout to a06a5b9359f31d946fe163b9038586982971ae49 2023-08-14 10:25:23 -06:00
zliang b8208794a3 move cpp-statsd-client to deps 2023-08-14 10:23:22 -06:00
zliang 12bf6188ae Merge branch 'main' into machamp-release-publish-image 2023-08-11 17:21:51 -06:00
Zhaozhen Liang cb147defbd Merge pull request #212 from Snapchat/migrate-keydb_modstatsd
migrate keydb_modstatsd to keydb-internal
2023-08-11 15:40:41 -06:00
zliang 4d56a1c5ed have clean also trigger keydb_modstatsd clean 2023-08-11 15:19:53 -06:00
zliang 289df10eb1 update 2023-08-11 15:16:10 -06:00
zliang 6e0305828e include trigger keydb_modstatsd Makefile in modules Makefile 2023-08-11 15:14:35 -06:00
zliang 6e1fbb2d14 add submodule cpp-statsd-client 2023-08-11 13:34:23 -06:00
zliang c94560f0ba rm 2023-08-11 13:32:20 -06:00
zliang db3fb7e9fe migrate keydb_modstatsd to keydb-internal 2023-08-11 13:26:28 -06:00
zliang 7a496d3dde address intentation and use default release 2023-08-10 14:08:37 -06:00
zliang 7bce881287 add release publish docker image 2023-08-10 11:29:07 -06:00
zliang 353695887a fix the working dir in Dockerfile 2023-08-09 11:44:33 -06:00
zliang 4fe4b235b2 add docker build 2023-08-08 19:28:44 -06:00
Malavan Sotheeswaran 747eb8067e disk space test 2023-06-29 21:50:05 -07:00
Malavan Sotheeswaran 1d547f89e1 1 second between each check 2023-06-28 17:44:36 -07:00
Malavan Sotheeswaran 9281b728d5 use dedicated db for load test to avoid loading other keys 2023-06-28 15:50:24 -07:00
Malavan Sotheeswaran 04cc2c01c6 change expire test to wait_for_condition 2023-06-28 00:27:51 -07:00
Malavan Sotheeswaran f681ca1a9f Merge remote-tracking branch 'internal/main' into flash_expiration 2023-06-27 15:25:47 -07:00
Malavan Sotheeswaran 336202eba5 strict < 2023-06-27 11:43:13 -07:00
Malavan Sotheeswaran 597dd12498 flash eviction test working 2023-06-27 00:06:32 -07:00
Malavan Sotheeswaran 7f86f4f876 WIP flash eviction tests 2023-06-26 22:06:38 -07:00
Malavan Sotheeswaran ea7838eb46 fix test 2023-06-26 21:35:09 -07:00
Malavan Sotheeswaran eb2018a423 reject versions before 6.3.4 2023-06-23 20:33:45 -07:00
Malavan Sotheeswaran 0eb118731e fix subkey exprires 2023-06-23 18:31:19 -07:00
Malavan Sotheeswaran a0a264a11c figured out the bug! 2023-06-23 18:20:36 -07:00
Malavan Sotheeswaran 79b3490f49 fix warnings 2023-06-23 16:52:46 -07:00
Malavan Sotheeswaran 178df4ddc6 respect sample count 2023-06-23 16:32:50 -07:00
Malavan Sotheeswaran 6504e7965a bake expire modifications into storage cache insert and erase 2023-06-23 12:21:47 -07:00
Malavan Sotheeswaran 7a9d4bbc31 some refactoring to avoid duplicate code 2023-06-23 12:03:08 -07:00
Malavan Sotheeswaran 0c0f8581f5 brackets to avoid ambiguos else 2023-06-21 19:15:11 -07:00
Malavan Sotheeswaran 967bd78658 only delete if exists 2023-06-21 19:12:38 -07:00
Malavan Sotheeswaran 605f369d65 remove expires from storage provider when removed from memory 2023-06-21 18:34:49 -07:00
Malavan Sotheeswaran c6871a3179 run tests with flash 2023-06-21 16:36:47 -07:00
Malavan Sotheeswaran f0d9466561 missing nullptr check 2023-06-14 15:11:27 -07:00
Malavan Sotheeswaran ec3b1eb5c4 handle all keys case 2023-06-14 15:07:50 -07:00
Malavan Sotheeswaran e248fec27f for all keys we need to remove the prefix 2023-06-14 14:20:17 -07:00
Malavan Sotheeswaran eea8932aa7 unit test doesn't make sense 2023-06-13 23:34:59 -07:00
Malavan Sotheeswaran 98eaebd4c8 accurate config update message 2023-06-13 22:52:26 -07:00
Malavan Sotheeswaran 8e41dc3ed2 fix spacing 2023-06-13 19:19:48 -07:00
Malavan Sotheeswaran e1afce8a4a remove extra blank line 2023-06-13 19:19:04 -07:00
Malavan Sotheeswaran 63dedf054f add unit test for flash eviction 2023-06-13 19:12:26 -07:00
Malavan Sotheeswaran 5f1884fc36 include vector 2023-06-12 22:55:36 -07:00
Malavan Sotheeswaran e54fd922d9 update expire column during fast sync 2023-06-12 21:51:40 -07:00
Malavan Sotheeswaran b81ba8bfc9 Merge branch 'main' into flash_expiration 2023-06-12 15:09:37 -07:00
Malavan Sotheeswaran f737084170 mstime not ustime 2023-05-26 03:05:29 -07:00
Malavan Sotheeswaran 49f48d808d double check expire time 2023-05-26 03:00:15 -07:00
Malavan Sotheeswaran 71045949c2 fix include and crash 2023-05-26 02:42:19 -07:00
Malavan Sotheeswaran ef1483e1d4 fix crash 2023-05-25 14:01:19 -07:00
Malavan Sotheeswaran 708b8d941b actually add expires to rocksdb 2023-05-25 00:17:12 -07:00
Malavan Sotheeswaran 12fd46da0b add ability to set expires in storge provider 2023-05-24 21:57:12 -07:00
Malavan Sotheeswaran 5aff96c577 fixes 2023-05-24 15:07:15 -07:00
Malavan Sotheeswaran 5cb2ead650 refactor for time limited expire cycle 2023-05-24 14:55:41 -07:00
Malavan Sotheeswaran 6853b15d50 add random hashslot impl 2023-05-23 21:26:01 -07:00
Malavan Sotheeswaran f701161d0a more progress 2023-05-23 21:10:40 -07:00
Malavan Sotheeswaran 6a32023cfc use correct key variable 2023-05-23 21:05:23 -07:00
Malavan Sotheeswaran 6eb595d6b4 remove expire from memory when evicting from cache 2023-05-23 20:50:58 -07:00
Malavan Sotheeswaran edae100767 refactor towards new design 2023-05-23 20:47:15 -07:00
Malavan Sotheeswaran 90fc43b849 add get expire and get eviction candidate impls for rocksdb 2023-05-18 10:19:49 -07:00
Malavan Sotheeswaran d4857720f2 adding KeyDB side of flash expiration/eviction 2023-05-17 13:46:43 -07:00
Malavan Sotheeswaran cdfca6a42b add machamp script 2023-05-11 21:20:26 -07:00
Malavan Sotheeswaran bae5c0dad1 switch machamp to main branch 2023-05-11 21:06:31 -07:00
Malavan Sotheeswaran 8b5fced206 add machamp 2023-05-11 21:05:59 -07:00
Malavan Sotheeswaran e6c0e14cdd add fixed length prefix extractor 2023-05-11 12:46:47 -07:00
Malavan Sotheeswaran e47624dc8e add option to show logs of 1 server at a time 2023-05-10 22:21:27 -07:00
Malavan Sotheeswaran 76e103b9bf fix warnings 2023-05-10 15:25:39 -07:00
Malavan Sotheeswaran ac1bd8eec4 add assert to ensure correctness 2023-05-10 14:19:17 -07:00
Malavan Sotheeswaran 9bfb89bfd8 forgot ; 2023-05-10 14:16:18 -07:00
Malavan Sotheeswaran eb565ae8f7 check for count mismatch 2023-05-10 14:12:19 -07:00
Malavan Sotheeswaran bc37934f6f forgot return statement in getKeysInSlot 2023-05-09 21:10:35 -07:00
Malavan Sotheeswaran e0007d9687 add --flash option for tests 2023-05-09 21:07:54 -07:00
Malavan Sotheeswaran e52792fe2a add hashslot enum to test storage provider 2023-05-09 13:52:37 -07:00
Malavan Sotheeswaran 880ca46788 fix compile 2023-05-09 13:49:19 -07:00
Malavan Sotheeswaran 6e1d6146e0 implement slot to keys with rocksdb 2023-05-09 12:36:48 -07:00
Malavan Sotheeswaran ce248d7b66 don't prefix internal keys 2023-05-09 11:30:08 -07:00
Malavan Sotheeswaran 4bdd2ed5f2 remove hashslot prefix when loading from rocksdb 2023-05-08 21:53:56 -07:00
Malavan Sotheeswaran e7ba8452bd Merge remote-tracking branch 'origin/main' into flash_slot_to_key 2023-05-08 13:03:48 -07:00
Malavan Sotheeswaran b9f049a25d don't need to offset internal keys 2023-05-05 15:45:09 -07:00
Malavan Sotheeswaran e69bfd5da6 add hash prefixing to rocksdb 2023-05-05 12:22:29 -07:00
30 changed files with 143 additions and 282 deletions

No files matched your search

+1 -6
View File
@@ -53,7 +53,7 @@ RUN set -eux; \
grep -E '^ *createBoolConfig[(]"protected-mode",.*, *1 *,.*[)],$' ./src/config.cpp; \
sed -ri 's!^( *createBoolConfig[(]"protected-mode",.*, *)1( *,.*[)],)$!\10\2!' ./src/config.cpp; \
grep -E '^ *createBoolConfig[(]"protected-mode",.*, *0 *,.*[)],$' ./src/config.cpp; \
make -j$(nproc) BUILD_TLS=yes ENABLE_FLASH=yes; \
make -j$(nproc) BUILD_TLS=yes; \
cd src; \
strip keydb-cli keydb-benchmark keydb-check-rdb keydb-check-aof keydb-diagnostic-tool keydb-sentinel keydb-server; \
mv keydb-server keydb-cli keydb-benchmark keydb-check-rdb keydb-check-aof keydb-diagnostic-tool keydb-sentinel /usr/local/bin/; \
@@ -83,7 +83,6 @@ RUN \
sed -i 's/^\(logfile .*\)$/# \1/' /etc/keydb/keydb.conf; \
sed -i 's/protected-mode yes/protected-mode no/g' /etc/keydb/keydb.conf; \
sed -i 's/^\(bind .*\)$/# \1/' /etc/keydb/keydb.conf; \
cd /usr/local/bin; \
ln -s keydb-cli redis-cli; \
cd /etc/keydb; \
ln -s keydb.conf redis.conf; \
@@ -97,10 +96,6 @@ RUN set -eux; \
echo 'if [ "${1#-}" != "$1" ] || [ "${1%.conf}" != "$1" ]; then' >> /usr/local/bin/docker-entrypoint.sh; \
echo ' set -- keydb-server "$@"' >> /usr/local/bin/docker-entrypoint.sh; \
echo 'fi' >> /usr/local/bin/docker-entrypoint.sh; \
echo '# if KEYDB_PASSWORD is set, add it to the arguments' >> /usr/local/bin/docker-entrypoint.sh; \
echo 'if [ -n "$KEYDB_PASSWORD" ]; then' >> /usr/local/bin/docker-entrypoint.sh; \
echo ' set -- "$@" --requirepass "${KEYDB_PASSWORD}"' >> /usr/local/bin/docker-entrypoint.sh; \
echo 'fi' >> /usr/local/bin/docker-entrypoint.sh; \
echo "# allow the container to be started with `--user`" >> /usr/local/bin/docker-entrypoint.sh; \
echo 'if [ "$1" = "keydb-server" -a "$(id -u)" = "0" ]; then' >> /usr/local/bin/docker-entrypoint.sh; \
echo " find . \! -user keydb -exec chown keydb '{}' +" >> /usr/local/bin/docker-entrypoint.sh; \
+4 -9
View File
@@ -1,11 +1,11 @@
FROM alpine:3.18
FROM alpine:3.12
# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
RUN addgroup -S -g 1000 keydb && adduser -S -G keydb -u 999 keydb
RUN mkdir -p /etc/keydb
ARG BRANCH
RUN set -eux; \
\
apk add --no-cache su-exec tini; \
apk add --no-cache su-exec; \
apk add --no-cache --virtual .build-deps \
coreutils \
gcc \
@@ -32,7 +32,7 @@ RUN set -eux; \
grep -E '^ *createBoolConfig[(]"protected-mode",.*, *1 *,.*[)],$' ./src/config.cpp; \
sed -ri 's!^( *createBoolConfig[(]"protected-mode",.*, *)1( *,.*[)],)$!\10\2!' ./src/config.cpp; \
grep -E '^ *createBoolConfig[(]"protected-mode",.*, *0 *,.*[)],$' ./src/config.cpp; \
make -j$(nproc) BUILD_TLS=yes ENABLE_FLASH=yes; \
make -j$(nproc) BUILD_TLS=yes; \
cd src; \
strip keydb-cli keydb-benchmark keydb-check-rdb keydb-check-aof keydb-diagnostic-tool keydb-sentinel keydb-server; \
mv keydb-server keydb-cli keydb-benchmark keydb-check-rdb keydb-check-aof keydb-diagnostic-tool keydb-sentinel /usr/local/bin/; \
@@ -54,7 +54,6 @@ RUN set -eux; \
sed -i 's/^\(logfile .*\)$/# \1/' /etc/keydb/keydb.conf; \
sed -i 's/protected-mode yes/protected-mode no/g' /etc/keydb/keydb.conf; \
sed -i 's/^\(bind .*\)$/# \1/' /etc/keydb/keydb.conf; \
cd /usr/local/bin; \
ln -s keydb-cli redis-cli; \
cd /etc/keydb; \
ln -s keydb.conf redis.conf; \
@@ -68,10 +67,6 @@ RUN set -eux; \
echo 'if [ "${1#-}" != "$1" ] || [ "${1%.conf}" != "$1" ]; then' >> /usr/local/bin/docker-entrypoint.sh; \
echo ' set -- keydb-server "$@"' >> /usr/local/bin/docker-entrypoint.sh; \
echo 'fi' >> /usr/local/bin/docker-entrypoint.sh; \
echo '# if KEYDB_PASSWORD is set, add it to the arguments' >> /usr/local/bin/docker-entrypoint.sh; \
echo 'if [ -n "$KEYDB_PASSWORD" ]; then' >> /usr/local/bin/docker-entrypoint.sh; \
echo ' set -- "$@" --requirepass "${KEYDB_PASSWORD}"' >> /usr/local/bin/docker-entrypoint.sh; \
echo 'fi' >> /usr/local/bin/docker-entrypoint.sh; \
echo "# allow the container to be started with `--user`" >> /usr/local/bin/docker-entrypoint.sh; \
echo 'if [ "$1" = "keydb-server" -a "$(id -u)" = "0" ]; then' >> /usr/local/bin/docker-entrypoint.sh; \
echo " find . \! -user keydb -exec chown keydb '{}' +" >> /usr/local/bin/docker-entrypoint.sh; \
@@ -81,6 +76,6 @@ RUN set -eux; \
chmod +x /usr/local/bin/docker-entrypoint.sh
VOLUME /data
WORKDIR /data
ENTRYPOINT ["tini", "--", "docker-entrypoint.sh"]
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 6379
CMD ["keydb-server", "/etc/keydb/keydb.conf"]
+1 -1
View File
@@ -44,7 +44,7 @@ public:
endWriteBatch();
}
virtual std::vector<std::string> getExpirationCandidates(unsigned int count) = 0;
virtual std::vector<std::string> getExpirationCandidates(unsigned int count, long long time) = 0;
virtual std::vector<std::string> getEvictionCandidates(unsigned int count) = 0;
virtual void setExpire(const char *key, size_t cchKey, long long expire) = 0;
virtual void removeExpire(const char *key, size_t cchKey, long long expire) = 0;
-1
View File
@@ -358,7 +358,6 @@ endif
OS := $(shell cat /etc/os-release | grep ID= | head -n 1 | cut -d'=' -f2)
ifeq ($(OS),alpine)
FINAL_CXXFLAGS+=-DUNW_LOCAL_ONLY
FINAL_CXXFLAGS+=-DALPINE
FINAL_LIBS += -lunwind
endif
+1 -1
View File
@@ -51,7 +51,7 @@ public:
bool enumerate(IStorage::callback fn) const { return m_spstorage->enumerate(fn); }
bool enumerate_hashslot(IStorage::callback fn, unsigned int hashslot) const { return m_spstorage->enumerate_hashslot(fn, hashslot); }
std::vector<std::string> getExpirationCandidates(unsigned int count) { return m_spstorage->getExpirationCandidates(count); }
std::vector<std::string> getExpirationCandidates(unsigned int count, long long time) { return m_spstorage->getExpirationCandidates(count, time); }
std::vector<std::string> getEvictionCandidates(unsigned int count) { return m_spstorage->getEvictionCandidates(count); }
void setExpire(const char *key, size_t cchKey, long long expire) { m_spstorage->setExpire(key, cchKey, expire); }
void removeExpire(const char *key, size_t cchKey, long long expire) { m_spstorage->removeExpire(key, cchKey, expire); }
+1 -30
View File
@@ -113,8 +113,6 @@ enum class AE_ASYNC_OP
PostCppFunction,
DeleteFileEvent,
CreateFileEvent,
PostAsynDBFunction,
};
struct aeCommand
@@ -127,8 +125,6 @@ struct aeCommand
aePostFunctionProc *proc;
aeFileProc *fproc;
std::function<void()> *pfn;
aePostFunctionTokenProc* tproc;
};
void *clientData;
};
@@ -179,17 +175,6 @@ void aeProcessCmd(aeEventLoop *eventLoop, int fd, void *, int )
(*cmd.pfn)();
delete cmd.pfn;
break;
}
case AE_ASYNC_OP::PostAsynDBFunction:
{ //added to support async api IStorage
if (cmd.fLock && !ulock.owns_lock()) {
g_forkLock.releaseRead();
ulock.lock();
g_forkLock.acquireRead();
}
((aePostFunctionTokenProc*)cmd.tproc)(eventLoop,(StorageToken*)cmd.clientData);
break;
}
break;
}
@@ -271,20 +256,6 @@ int aePostFunction(aeEventLoop *eventLoop, aePostFunctionProc *proc, void *arg)
return AE_OK;
}
int aePostFunction(aeEventLoop *eventLoop, aePostFunctionTokenProc *proc, StorageToken *token)
{
//added to support async api IStorage
aeCommand cmd = {};
cmd.op = AE_ASYNC_OP::PostAsynDBFunction;
cmd.tproc = proc;
cmd.clientData = (void*)token;
cmd.fLock = true;
auto size = write(eventLoop->fdCmdWrite, &cmd, sizeof(cmd));
if (size != sizeof(cmd))
return AE_ERR;
return AE_OK;
}
int aePostFunction(aeEventLoop *eventLoop, std::function<void()> fn, bool fLock, bool fForceQueue)
{
if (eventLoop == g_eventLoopThisThread && !fForceQueue)
@@ -890,7 +861,7 @@ void aeReleaseForkLock()
void aeForkLockInChild()
{
g_forkLock.setMulti(false);
g_forkLock.setNotify(false);
}
int aeThreadOwnsLock()
+1 -5
View File
@@ -72,15 +72,13 @@ extern "C" {
#define AE_NOTUSED(V) ((void) V)
struct aeEventLoop;
/* Types and data structures */
typedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask);
typedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData);
typedef void aeEventFinalizerProc(struct aeEventLoop *eventLoop, void *clientData);
typedef void aeBeforeSleepProc(struct aeEventLoop *eventLoop);
typedef void aePostFunctionProc(void *pvArgs);
//added to support async api IStorage
struct StorageToken;
typedef void aePostFunctionTokenProc(struct aeEventLoop *el, struct StorageToken *token);
/* File event structure */
typedef struct aeFileEvent {
@@ -136,8 +134,6 @@ int aePostFunction(aeEventLoop *eventLoop, aePostFunctionProc *proc, void *arg);
#ifdef __cplusplus
} // EXTERN C
int aePostFunction(aeEventLoop *eventLoop, std::function<void()> fn, bool fLock = true, bool fForceQueue = false);
//added to support async api IStorage
int aePostFunction(aeEventLoop *eventLoop, aePostFunctionTokenProc *proc, StorageToken *token);
extern "C" {
#endif
void aeDeleteEventLoop(aeEventLoop *eventLoop);
+1 -3
View File
@@ -5991,9 +5991,7 @@ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, in
/* If it is not the first key, make sure it is exactly
* the same key as the first we saw. */
if (!equalStringObjects(firstkey,thiskey)) {
clusterNode* nThisKey = g_pserver->cluster->slots[thisslot];
if ((slot != thisslot) && (nThisKey != n || migrating_slot || importing_slot || g_pserver->cluster->migrating_slots_to[slot] != nullptr || g_pserver->cluster->importing_slots_from[slot] != nullptr)) {
if (slot != thisslot) {
/* Error: multiple keys from different slots. */
getKeysFreeResult(&result);
if (error_code)
+1 -2
View File
@@ -2946,7 +2946,7 @@ standardConfig configs[] = {
createLongLongConfig("latency-monitor-threshold", NULL, MODIFIABLE_CONFIG, 0, LLONG_MAX, g_pserver->latency_monitor_threshold, 0, INTEGER_CONFIG, NULL, NULL),
createLongLongConfig("proto-max-bulk-len", NULL, MODIFIABLE_CONFIG, 1024*1024, LLONG_MAX, g_pserver->proto_max_bulk_len, 512ll*1024*1024, MEMORY_CONFIG, NULL, NULL), /* Bulk request max size */
createLongLongConfig("stream-node-max-entries", NULL, MODIFIABLE_CONFIG, 0, LLONG_MAX, g_pserver->stream_node_max_entries, 100, INTEGER_CONFIG, NULL, NULL),
createLongLongConfig("repl-backlog-size", NULL, MODIFIABLE_CONFIG, 1, LLONG_MAX, g_pserver->repl_backlog_config_size, 1024*1024, MEMORY_CONFIG, NULL, updateReplBacklogSize), /* Default: 1mb */
createLongLongConfig("repl-backlog-size", NULL, MODIFIABLE_CONFIG, 1, LLONG_MAX, g_pserver->repl_backlog_size, 1024*1024, MEMORY_CONFIG, NULL, updateReplBacklogSize), /* Default: 1mb */
createLongLongConfig("repl-backlog-disk-reserve", NULL, IMMUTABLE_CONFIG, 0, LLONG_MAX, cserver.repl_backlog_disk_size, 0, MEMORY_CONFIG, NULL, NULL),
createLongLongConfig("max-snapshot-slip", NULL, MODIFIABLE_CONFIG, 0, 5000, g_pserver->snapshot_slip, 400, 0, NULL, NULL),
createLongLongConfig("max-rand-count", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX/2, g_pserver->rand_total_threshold, LONG_MAX/2, 0, NULL, NULL),
@@ -2982,7 +2982,6 @@ standardConfig configs[] = {
createSDSConfig("availability-zone", NULL, MODIFIABLE_CONFIG, 0, g_pserver->sdsAvailabilityZone, "", NULL, NULL),
createIntConfig("overload-protect-percent", NULL, MODIFIABLE_CONFIG, 0, 200, g_pserver->overload_protect_threshold, 0, INTEGER_CONFIG, NULL, NULL),
createIntConfig("force-eviction-percent", NULL, MODIFIABLE_CONFIG, 0, 100, g_pserver->force_eviction_percent, 0, INTEGER_CONFIG, NULL, NULL),
createBoolConfig("enable-async-rehash", NULL, MODIFIABLE_CONFIG, g_pserver->enable_async_rehash, 1, NULL, NULL),
#ifdef USE_OPENSSL
createIntConfig("tls-port", NULL, MODIFIABLE_CONFIG, 0, 65535, g_pserver->tls_port, 0, INTEGER_CONFIG, NULL, updateTLSPort), /* TCP port. */
+6 -8
View File
@@ -2703,6 +2703,11 @@ void redisDbPersistentData::prepOverwriteForSnapshot(char *key)
auto itr = m_pdbSnapshot->find_cached_threadsafe(key);
if (itr.key() != nullptr)
{
if (itr.val()->FExpires()) {
// Note: I'm sure we could handle this, but its too risky at the moment.
// There are known bugs doing this with expires
return;
}
sds keyNew = sdsdupshared(itr.key());
if (dictAdd(m_pdictTombstone, keyNew, (void*)dictHashKey(m_pdict, key)) != DICT_OK)
sdsfree(keyNew);
@@ -2740,13 +2745,6 @@ void redisDbPersistentData::clear(void(callback)(void*))
if (m_spstorage != nullptr)
m_spstorage->clear(callback);
dictEmpty(m_pdictTombstone,callback);
// To avoid issues with async rehash we completly free the old dict and create a fresh one
dictRelease(m_pdict);
dictRelease(m_pdictTombstone);
m_pdict = dictCreate(&dbDictType, this);
m_pdictTombstone = dictCreate(&dbTombstoneDictType, this);
m_pdbSnapshot = nullptr;
m_numexpires = 0;
}
@@ -2882,10 +2880,10 @@ LNotFound:
{
dictAdd(m_pdict, sdsNewKey, o);
o->SetFExpires(spexpire != nullptr);
if (spexpire != nullptr) {
o->expire = std::move(*spexpire);
}
o->SetFExpires(spexpire != nullptr);
g_pserver->stat_storage_provider_read_hits++;
} else {
sdsfree(sdsNewKey);
+21 -67
View File
@@ -79,7 +79,6 @@ void printCrashReport(void);
void bugReportEnd(int killViaSignal, int sig);
void logStackTrace(void *eip, int uplevel);
void getTempFileName(char tmpfile[], int tmpfileNum);
bool initializeStorageProvider(const char **err);
/* ================================= Debugging ============================== */
@@ -309,7 +308,7 @@ void computeDatasetDigest(unsigned char *final) {
mixDigest(final,&aux,sizeof(aux));
/* Iterate this DB writing every entry */
db->iterate_threadsafe([final](const char *key, robj_roptr o)->bool {
db->iterate_threadsafe([final, db](const char *key, robj_roptr o)->bool {
unsigned char digest[20];
robj *keyobj;
@@ -536,75 +535,30 @@ NULL
return;
}
}
if (g_pserver->m_pstorageFactory) {
protectClient(c);
for (int idb = 0; idb < cserver.dbnum; ++idb) {
if (g_pserver->db[idb]->processChanges(false))
g_pserver->db[idb]->commitChanges();
g_pserver->db[idb]->storageProviderDelete();
}
delete g_pserver->metadataDb;
if (flush) emptyDb(-1,EMPTYDB_NO_FLAGS,NULL);
delete g_pserver->m_pstorageFactory;
const char *err;
if (!initializeStorageProvider(&err))
{
serverLog(LL_WARNING, "Failed to initialize storage provider: %s",err);
exit(EXIT_FAILURE);
}
g_pserver->metadataDb = g_pserver->m_pstorageFactory->createMetadataDb();
for (int idb = 0; idb < cserver.dbnum; ++idb)
{
int dbid = idb;
std::string dbid_key = "db-" + std::to_string(idb);
g_pserver->metadataDb->retrieve(dbid_key.c_str(), dbid_key.length(), [&](const char *, size_t, const void *data, size_t){
dbid = *(int*)data;
});
delete g_pserver->db[idb];
g_pserver->db[idb] = new (MALLOC_LOCAL) redisDb();
g_pserver->db[idb]->initialize(dbid);
}
moduleFireServerEvent(REDISMODULE_EVENT_LOADING, REDISMODULE_SUBEVENT_LOADING_FLASH_START, NULL);
for (int idb = 0; idb < cserver.dbnum; ++idb)
{
g_pserver->db[idb]->storageProviderInitialize();
g_pserver->db[idb]->trackChanges(false);
}
moduleFireServerEvent(REDISMODULE_EVENT_LOADING, REDISMODULE_SUBEVENT_LOADING_ENDED, NULL);
unprotectClient(c);
} else {
/* The default behavior is to save the RDB file before loading
* it back. */
if (save) {
rdbSaveInfo rsi, *rsiptr;
rsiptr = rdbPopulateSaveInfo(&rsi);
if (rdbSave(nullptr, rsiptr) != C_OK) {
addReply(c,shared.err);
return;
}
}
/* The default behavior is to remove the current dataset from
* memory before loading the RDB file, however when MERGE is
* used together with NOFLUSH, we are able to merge two datasets. */
if (flush) emptyDb(-1,EMPTYDB_NO_FLAGS,NULL);
protectClient(c);
int ret = rdbLoadFile(g_pserver->rdb_filename,NULL,flags);
unprotectClient(c);
if (ret != C_OK) {
addReplyError(c,"Error trying to load the RDB dump");
/* The default behavior is to save the RDB file before loading
* it back. */
if (save) {
rdbSaveInfo rsi, *rsiptr;
rsiptr = rdbPopulateSaveInfo(&rsi);
if (rdbSave(nullptr, rsiptr) != C_OK) {
addReply(c,shared.err);
return;
}
}
/* The default behavior is to remove the current dataset from
* memory before loading the RDB file, however when MERGE is
* used together with NOFLUSH, we are able to merge two datasets. */
if (flush) emptyDb(-1,EMPTYDB_NO_FLAGS,NULL);
protectClient(c);
int ret = rdbLoadFile(g_pserver->rdb_filename,NULL,flags);
unprotectClient(c);
if (ret != C_OK) {
addReplyError(c,"Error trying to load the RDB dump");
return;
}
serverLog(LL_WARNING,"DB reloaded by DEBUG RELOAD");
addReply(c,shared.ok);
} else if (!strcasecmp(szFromObj(c->argv[1]),"loadaof")) {
+3 -5
View File
@@ -518,13 +518,11 @@ void pexpireMemberAtCommand(client *c)
} while (sampled == 0 ||
(expired*100/sampled) > config_cycle_acceptable_stale);
} else {
long prev_expired;
long long now = mstime();
long long now;
size_t tried = 0;
std::vector<std::string> keys;
do {
prev_expired = total_expired;
keys = db->getStorageCache()->getExpirationCandidates(ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP);
keys = db->getStorageCache()->getExpirationCandidates(ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP, now);
for (std::string key : keys) {
robj* keyobj = createStringObject(key.c_str(), key.size());
db->find(szFromObj(keyobj));
@@ -535,7 +533,7 @@ void pexpireMemberAtCommand(client *c)
}
total_sampled += keys.size();
elapsed = ustime()-start;
} while (keys.size() > 0 && (elapsed < timelimit) && (total_expired - prev_expired) > 0);
} while (keys.size() > 0 && (elapsed < timelimit));
if (ustime()-start > timelimit) {
timelimit_exit = 1;
-4
View File
@@ -160,8 +160,6 @@ public:
expireEntry &operator=(expireEntry &&e)
{
if (FFat())
delete pfatentry();
s = e.s;
e.s.m_whenAndPtrUnion = 0;
e.s.fFat = false;
@@ -169,8 +167,6 @@ public:
}
expireEntry &operator=(expireEntry &e) {
if (FFat())
delete pfatentry();
if (e.FFat()) {
s.m_whenAndPtrUnion = reinterpret_cast<long long>(new expireEntryFat(*e.pfatentry()));
s.fFat = true;
-1
View File
@@ -19,7 +19,6 @@ static size_t getMemKey(std::string key) {
}
return 0;
# else
(void)key;
return 0;
# endif
}
+3 -4
View File
@@ -690,9 +690,8 @@ void moduleHandlePropagationAfterCommandCallback(RedisModuleCtx *ctx) {
}
/* Free the context after the user function was called. */
void moduleFreeContext(RedisModuleCtx *ctx, bool propogate) {
if (propogate)
moduleHandlePropagationAfterCommandCallback(ctx);
void moduleFreeContext(RedisModuleCtx *ctx) {
moduleHandlePropagationAfterCommandCallback(ctx);
autoMemoryCollect(ctx);
poolAllocRelease(ctx);
if (ctx->postponed_arrays) {
@@ -7058,7 +7057,7 @@ RedisModuleString *RM_DictPrev(RedisModuleCtx *ctx, RedisModuleDictIter *di, voi
/* Compare the element currently pointed by the iterator to the specified
* element given by key/keylen, according to the operator 'op' (the set of
* valid operators are the same valid for RedisModule_DictIteratorStart).
* If the comparison is successful the command returns REDISMODULE_OK
* If the comparision is successful the command returns REDISMODULE_OK
* otherwise REDISMODULE_ERR is returned.
*
* This is useful when we want to just emit a lexicographical range, so
+1 -1
View File
@@ -4,7 +4,7 @@ OBJECT_FILES := modmain.o
MODSNAP_CXX_FLAGS := -std=gnu++14
%.o: %.cpp
$(CXX) -o $@ -c $< $(MODULE_FLAGS) -I../../../deps/cpp-statsd-client/include $(MODSNAP_CXX_FLAGS) -g
$(CXX) -o $@ -c $< $(MODULE_FLAGS) -I../../../deps/cpp-statsd-client/include $(MODSNAP_CXX_FLAGS)
modstatsd.so: $(OBJECT_FILES)
$(CXX) -shared $(OBJECT_FILES) -o modstatsd.so
+11 -14
View File
@@ -76,7 +76,7 @@ std::string m_strPrefix { "keydb" };
const std::regex g_replica_or_db_info_regex { "^(slave|db)(\\d+)" };
const char *g_string_counter_separator = "__";
const uint64_t g_stats_buffer_size_bytes = 1600;
std::string nodeName;
utsname sysName;
int unameResult;
enum class StatsD_Type {
@@ -582,7 +582,7 @@ void event_cron_handler(struct RedisModuleCtx *ctx, RedisModuleEvent eid, uint64
size_t startTime = ustime();
#ifdef __linux__
/* Log CPU Usage */
/* Log CPU Usage */
static long long s_mscpuLast = 0;
struct rusage self_ru;
getrusage(RUSAGE_SELF, &self_ru);
@@ -591,7 +591,7 @@ void event_cron_handler(struct RedisModuleCtx *ctx, RedisModuleEvent eid, uint64
+ (self_ru.ru_stime.tv_sec * 1000) + (self_ru.ru_stime.tv_usec / 1000);
g_stats->gauge("cpu_load_perc", ((double)(mscpuCur - s_mscpuLast) / ((curTime - lastTime)*1000))*100, false /* prefixOnly */);
g_stats->gauge("cpu_load_perc", (double)(mscpuCur - s_mscpuLast) / ((curTime - lastTime)*1000), true /* prefixOnly */);
s_mscpuLast = mscpuCur;
#endif
@@ -600,7 +600,7 @@ void event_cron_handler(struct RedisModuleCtx *ctx, RedisModuleEvent eid, uint64
/* node name */
if (unameResult == 0) {
g_stats->increment("node_name" + std::string(g_string_counter_separator) + nodeName);
g_stats->increment("node_name" + std::string(g_string_counter_separator) + sysName.nodename);
}
/* Log INFO Fields */
@@ -653,7 +653,7 @@ void event_cron_handler(struct RedisModuleCtx *ctx, RedisModuleEvent eid, uint64
reply = RedisModule_Call(ctx, "dbsize", "");
long long keys = RedisModule_CallReplyInteger(reply);
RedisModule_FreeCallReply(reply);
g_stats->gauge("keys", keys, false /* prefixOnly */);
g_stats->gauge("keys", keys);
RedisModule_Log(ctx, REDISMODULE_LOGLEVEL_DEBUG, "Emitting metric \"keys\": %llu", keys);
g_stats->timing("emit_keys_metric_time_taken_us", ustime() - commandStartTime);
@@ -672,20 +672,17 @@ extern "C" int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv,
RedisModule_AutoMemory(ctx);
/* Use pod name if available*/
const char *podName = getenv("POD_NAME");
utsname sysName;
unameResult = uname(&sysName);
if (unameResult == 0) {
nodeName = std::string(sysName.nodename);
std::replace(nodeName.begin(), nodeName.end(), '.', '-');
}
if (podName != nullptr) {
m_strPrefix = podName;
std::replace(m_strPrefix.begin(), m_strPrefix.end(), '.', '-');
}
else if (unameResult == 0) {
m_strPrefix = nodeName;
unameResult = 1;
else {
if (unameResult == 0) {
m_strPrefix = std::string(sysName.nodename);
unameResult = 1;
}
}
std::replace(m_strPrefix.begin(), m_strPrefix.end(), '.', '-');
for (int iarg = 0; iarg < argc; ++iarg) {
size_t len = 0;
-2
View File
@@ -46,7 +46,6 @@ robj *createObject(int type, void *ptr) {
char *oB = (char*)zcalloc(sizeof(robj)+mvccExtraBytes, MALLOC_SHARED);
robj *o = reinterpret_cast<robj*>(oB + mvccExtraBytes);
new (o) redisObject;
o->type = type;
o->encoding = OBJ_ENCODING_RAW;
o->m_ptr = ptr;
@@ -419,7 +418,6 @@ void decrRefCount(robj_roptr o) {
case OBJ_NESTEDHASH: freeNestedHashObject(o); break;
default: serverPanic("Unknown object type"); break;
}
o->~redisObject();
if (g_pserver->fActiveReplica) {
zfree(reinterpret_cast<redisObjectExtended*>(o.unsafe_robjcast())-1);
} else {
+1 -1
View File
@@ -2542,7 +2542,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, sds key, int *error, uint64_t mvcc_ts
* encoding version in the lower 10 bits of the module ID. */
void *ptr = mt->rdb_load(&io,moduleid&1023);
if (io.ctx) {
moduleFreeContext(io.ctx, false /* propogate */);
moduleFreeContext(io.ctx);
zfree(io.ctx);
}
+33 -47
View File
@@ -8,46 +8,38 @@ class readWriteLock {
int m_readCount = 0;
int m_writeCount = 0;
bool m_writeWaiting = false;
bool m_multi = true;
bool m_notify = true;
public:
readWriteLock(const char *name) : m_readLock(name), m_writeLock(name) {}
void acquireRead() {
std::unique_lock<fastlock> rm(m_readLock, std::defer_lock);
if (m_multi) {
rm.lock();
while (m_writeCount > 0 || m_writeWaiting)
m_cv.wait(rm);
}
std::unique_lock<fastlock> rm(m_readLock);
while (m_writeCount > 0 || m_writeWaiting)
m_cv.wait(rm);
m_readCount++;
}
bool tryAcquireRead() {
std::unique_lock<fastlock> rm(m_readLock, std::defer_lock);
if (m_multi) {
if (!rm.try_lock())
return false;
if (m_writeCount > 0 || m_writeWaiting)
return false;
}
if (!rm.try_lock())
return false;
if (m_writeCount > 0 || m_writeWaiting)
return false;
m_readCount++;
return true;
}
void acquireWrite(bool exclusive = true) {
std::unique_lock<fastlock> rm(m_readLock, std::defer_lock);
if (m_multi) {
rm.lock();
m_writeWaiting = true;
while (m_readCount > 0)
std::unique_lock<fastlock> rm(m_readLock);
m_writeWaiting = true;
while (m_readCount > 0)
m_cv.wait(rm);
if (exclusive) {
/* Another thread might have the write lock while we have the read lock
but won't be able to release it until they can acquire the read lock
so release the read lock and try again instead of waiting to avoid deadlock */
while(!m_writeLock.try_lock())
m_cv.wait(rm);
if (exclusive) {
/* Another thread might have the write lock while we have the internal lock
but won't be able to release it until they can acquire the internal lock
so release the internal lock and try again instead of waiting to avoid deadlock */
while(!m_writeLock.try_lock())
m_cv.wait(rm);
}
}
m_writeCount++;
m_writeWaiting = false;
@@ -60,38 +52,32 @@ public:
bool tryAcquireWrite(bool exclusive = true) {
std::unique_lock<fastlock> rm(m_readLock, std::defer_lock);
if (m_multi) {
if (!rm.try_lock())
if (!rm.try_lock())
return false;
if (m_readCount > 0)
return false;
if (exclusive)
if (!m_writeLock.try_lock())
return false;
if (m_readCount > 0)
return false;
if (exclusive)
if (!m_writeLock.try_lock())
return false;
}
m_writeCount++;
return true;
}
void releaseRead() {
std::unique_lock<fastlock> rm(m_readLock, std::defer_lock);
if (m_multi) {
rm.lock();
m_cv.notify_all();
}
std::unique_lock<fastlock> rm(m_readLock);
m_readCount--;
if (m_notify)
m_cv.notify_all();
}
void releaseWrite(bool exclusive = true) {
std::unique_lock<fastlock> rm(m_readLock, std::defer_lock);
std::unique_lock<fastlock> rm(m_readLock);
serverAssert(m_writeCount > 0);
if (m_multi) {
rm.lock();
if (exclusive)
m_writeLock.unlock();
m_cv.notify_all();
}
if (exclusive)
m_writeLock.unlock();
m_writeCount--;
if (m_notify)
m_cv.notify_all();
}
void downgradeWrite(bool exclusive = true) {
@@ -99,8 +85,8 @@ public:
acquireRead();
}
void setMulti(bool multi) {
m_multi = multi;
void setNotify(bool notify) {
m_notify = notify;
}
bool hasReader() {
+2 -4
View File
@@ -188,8 +188,6 @@ int bg_unlink(const char *filename) {
/* ---------------------------------- MASTER -------------------------------- */
bool createDiskBacklog() {
if (g_pserver->repl_backlog_disk != nullptr)
return true; // already exists
// Lets create some disk backed pages and add them here
std::string path = "./repl-backlog-temp" + std::to_string(gettid());
#if (defined __APPLE__ || defined __FreeBSD__)
@@ -3735,12 +3733,12 @@ retry_connect:
}
/* Prepare a suitable temp file for bulk transfer */
if (!useDisklessLoad() && !mi->isRocksdbSnapshotRepl) {
if (!useDisklessLoad()) {
while(maxtries--) {
auto dt = std::chrono::system_clock::now().time_since_epoch();
auto dtMillisecond = std::chrono::duration_cast<std::chrono::milliseconds>(dt);
snprintf(tmpfile,sizeof(tmpfile),
"temp-%lld.%ld.rdb",(long long)dtMillisecond.count(),(long int)getpid());
"temp-%d.%ld.rdb",(int)dtMillisecond.count(),(long int)getpid());
dfd = open(tmpfile,O_CREAT|O_WRONLY|O_EXCL,0644);
if (dfd != -1) break;
sleep(1);
+4 -6
View File
@@ -2137,7 +2137,7 @@ void databasesCron(bool fMainThread) {
::dict *dict = g_pserver->db[rehash_db]->dictUnsafeKeyOnly();
/* Are we async rehashing? And if so is it time to re-calibrate? */
/* The recalibration limit is a prime number to ensure balancing across threads */
if (g_pserver->enable_async_rehash && rehashes_per_ms > 0 && async_rehashes < 131 && !cserver.active_defrag_enabled && cserver.cthreads > 1 && dictSize(dict) > 2048 && dictIsRehashing(dict) && !g_pserver->loading && aeLockContention() > 1) {
if (rehashes_per_ms > 0 && async_rehashes < 131 && !cserver.active_defrag_enabled && cserver.cthreads > 1 && dictSize(dict) > 2048 && dictIsRehashing(dict) && !g_pserver->loading) {
serverTL->rehashCtl = dictRehashAsyncStart(dict, rehashes_per_ms * ((1000 / g_pserver->hz) / 10)); // Estimate 10% CPU time spent in lock contention
if (serverTL->rehashCtl)
++async_rehashes;
@@ -5663,8 +5663,7 @@ sds genRedisInfoString(const char *section) {
"lru_clock:%u\r\n"
"executable:%s\r\n"
"config_file:%s\r\n"
"availability_zone:%s\r\n"
"features:%s\r\n",
"availability_zone:%s\r\n",
KEYDB_SET_VERSION,
redisGitSHA1(),
strtol(redisGitDirty(),NULL,10) > 0,
@@ -5691,8 +5690,7 @@ sds genRedisInfoString(const char *section) {
lruclock,
cserver.executable ? cserver.executable : "",
cserver.configfile ? cserver.configfile : "",
g_pserver->sdsAvailabilityZone,
"cluster_mget");
g_pserver->sdsAvailabilityZone);
}
/* Clients */
@@ -7413,7 +7411,7 @@ static void validateConfiguration()
exit(EXIT_FAILURE);
}
g_pserver->repl_backlog_size = g_pserver->repl_backlog_config_size; // this is normally set in the update logic, but not on initial config
g_pserver->repl_backlog_config_size = g_pserver->repl_backlog_size; // this is normally set in the update logic, but not on initial config
}
int iAmMaster(void) {
+2 -4
View File
@@ -966,7 +966,6 @@ struct redisObjectExtended {
typedef struct redisObject {
friend redisObject *createEmbeddedStringObject(const char *ptr, size_t len);
friend redisObject *createObject(int type, void *ptr);
protected:
redisObject() {}
@@ -2306,7 +2305,6 @@ struct redisServer {
rax *errors; /* Errors table */
int activerehashing; /* Incremental rehash in serverCron() */
int active_defrag_running; /* Active defragmentation running (holds current scan aggressiveness) */
int enable_async_rehash = 1; /* Should we use the async rehash feature? */
int cronloops; /* Number of times the cron function run */
char runid[CONFIG_RUN_ID_SIZE+1]; /* ID always different at every exec. */
int sentinel_mode; /* True if this instance is a Sentinel. */
@@ -2919,7 +2917,7 @@ int moduleGetCommandKeysViaAPI(struct redisCommand *cmd, robj **argv, int argc,
moduleType *moduleTypeLookupModuleByID(uint64_t id);
void moduleTypeNameByID(char *name, uint64_t moduleid);
const char *moduleTypeModuleName(moduleType *mt);
void moduleFreeContext(struct RedisModuleCtx *ctx, bool propogate = true);
void moduleFreeContext(struct RedisModuleCtx *ctx);
void unblockClientFromModule(client *c);
void moduleHandleBlockedClients(int iel);
void moduleBlockedClientTimedOut(client *c);
@@ -3923,7 +3921,7 @@ void updateActiveReplicaMastersFromRsi(rdbSaveInfo *rsi);
uint64_t getMvccTstamp();
void incrementMvccTstamp();
#if __GNUC__ >= 7 && !defined(NO_DEPRECATE_FREE) && !defined(ALPINE)
#if __GNUC__ >= 7 && !defined(NO_DEPRECATE_FREE)
[[deprecated]]
void *calloc(size_t count, size_t size) noexcept;
[[deprecated]]
+1 -5
View File
@@ -587,12 +587,8 @@ bool redisDbPersistentDataSnapshot::iterate_threadsafe_core(std::function<bool(c
if (!fKeyOnly)
{
size_t offset = 0;
std::unique_ptr<expireEntry> spexpire = deserializeExpire((const char*)data, cbData, &offset);
deserializeExpire((const char*)data, cbData, &offset);
o = deserializeStoredObject(reinterpret_cast<const char*>(data)+offset, cbData-offset);
o->SetFExpires(spexpire != nullptr);
if (spexpire != nullptr) {
o->expire = std::move(*spexpire);
}
}
fContinue = fn(sdsKey, o);
if (o != nullptr)
+21 -31
View File
@@ -7,8 +7,6 @@
#include "../cluster.h"
#include "rocksdbfactor_internal.h"
template class std::basic_string<char>;
static const char keyprefix[] = INTERNAL_KEY_PREFIX;
rocksdb::Options DefaultRocksDBOptions();
@@ -26,9 +24,8 @@ bool FInternalKey(const char *key, size_t cch)
std::string getPrefix(unsigned int hashslot)
{
HASHSLOT_PREFIX_TYPE slot = HASHSLOT_PREFIX_ENDIAN((HASHSLOT_PREFIX_TYPE)hashslot);
char *hash_char = (char *)&slot;
return std::string(hash_char, HASHSLOT_PREFIX_BYTES);
char *hash_char = (char *)&hashslot;
return std::string(hash_char + (sizeof(unsigned int) - 2), 2);
}
std::string prefixKey(const char *key, size_t cchKey)
@@ -147,28 +144,16 @@ void RocksDBStorageProvider::retrieve(const char *key, size_t cchKey, callbackSi
size_t RocksDBStorageProvider::clear()
{
size_t celem = count();
auto options = m_spdb->GetOptions(m_spcolfamily.get());
auto status = m_spdb->DropColumnFamily(m_spcolfamily.get());
auto strName = m_spcolfamily->GetName();
rocksdb::ColumnFamilyHandle *handle = nullptr;
rocksdb::ColumnFamilyOptions cf_options(options);
rocksdb::ColumnFamilyOptions cf_options(m_pfactory->RocksDbOptions());
m_spdb->CreateColumnFamily(cf_options, strName, &handle);
m_spcolfamily = std::shared_ptr<rocksdb::ColumnFamilyHandle>(handle);
if (!status.ok())
throw status.ToString();
status = m_spdb->DropColumnFamily(m_spexpirecolfamily.get());
strName = m_spexpirecolfamily->GetName();
m_spdb->CreateColumnFamily(cf_options, strName, &handle);
m_spexpirecolfamily = std::shared_ptr<rocksdb::ColumnFamilyHandle>(handle);
if (!status.ok())
throw status.ToString();
m_count = 0;
return celem;
}
@@ -187,7 +172,7 @@ bool RocksDBStorageProvider::enumerate(callback fn) const
if (FInternalKey(it->key().data(), it->key().size()))
continue;
++count;
bool fContinue = fn(it->key().data()+HASHSLOT_PREFIX_BYTES, it->key().size()-HASHSLOT_PREFIX_BYTES, it->value().data(), it->value().size());
bool fContinue = fn(it->key().data()+2, it->key().size()-2, it->value().data(), it->value().size());
if (!fContinue)
break;
}
@@ -206,17 +191,17 @@ bool RocksDBStorageProvider::enumerate_hashslot(callback fn, unsigned int hashsl
std::string prefix = getPrefix(hashslot);
std::unique_ptr<rocksdb::Iterator> it = std::unique_ptr<rocksdb::Iterator>(m_spdb->NewIterator(ReadOptions(), m_spcolfamily.get()));
size_t count = 0;
for (it->Seek(prefix); it->Valid(); it->Next()) {
for (it->Seek(prefix.c_str()); it->Valid(); it->Next()) {
if (FInternalKey(it->key().data(), it->key().size()))
continue;
if (HASHSLOT_PREFIX_RECOVER(*(HASHSLOT_PREFIX_TYPE *)it->key().data()) != hashslot)
if (strncmp(it->key().data(),prefix.c_str(),2) != 0)
break;
++count;
bool fContinue = fn(it->key().data()+HASHSLOT_PREFIX_BYTES, it->key().size()-HASHSLOT_PREFIX_BYTES, it->value().data(), it->value().size());
bool fContinue = fn(it->key().data()+2, it->key().size()-2, it->value().data(), it->value().size());
if (!fContinue)
break;
}
bool full_iter = !it->Valid() || (HASHSLOT_PREFIX_RECOVER(*(HASHSLOT_PREFIX_TYPE *)it->key().data()) != hashslot);
bool full_iter = !it->Valid() || (strncmp(it->key().data(),prefix.c_str(),2) != 0);
if (full_iter && count != g_pserver->cluster->slots_keys_count[hashslot])
{
printf("WARNING: rocksdb hashslot count mismatch");
@@ -230,8 +215,7 @@ void RocksDBStorageProvider::setExpire(const char *key, size_t cchKey, long long
{
rocksdb::Status status;
std::unique_lock<fastlock> l(m_lock);
long long beExpire = htobe64(expire);
std::string prefix((const char *)&beExpire,sizeof(long long));
std::string prefix((const char *)&expire,sizeof(long long));
std::string strKey(key, cchKey);
if (m_spbatch != nullptr)
status = m_spbatch->Put(m_spexpirecolfamily.get(), rocksdb::Slice(prefix + strKey), rocksdb::Slice(strKey));
@@ -245,8 +229,7 @@ void RocksDBStorageProvider::removeExpire(const char *key, size_t cchKey, long l
{
rocksdb::Status status;
std::unique_lock<fastlock> l(m_lock);
long long beExpire = htobe64(expire);
std::string prefix((const char *)&beExpire,sizeof(long long));
std::string prefix((const char *)&expire,sizeof(long long));
std::string strKey(key, cchKey);
std::string fullKey = prefix + strKey;
if (!FExpireExists(fullKey))
@@ -259,14 +242,21 @@ void RocksDBStorageProvider::removeExpire(const char *key, size_t cchKey, long l
throw status.ToString();
}
std::vector<std::string> RocksDBStorageProvider::getExpirationCandidates(unsigned int count)
std::vector<std::string> RocksDBStorageProvider::getExpirationCandidates(unsigned int count, long long time)
{
std::vector<std::string> result;
std::unique_ptr<rocksdb::Iterator> it = std::unique_ptr<rocksdb::Iterator>(m_spdb->NewIterator(ReadOptions(), m_spexpirecolfamily.get()));
for (it->SeekToFirst(); it->Valid() && result.size() < count; it->Next()) {
for (it->SeekToFirst(); it->Valid() && (*((long long *)it->key().data()) < time) && (result.size() < count); it->Next()) {
if (FInternalKey(it->key().data(), it->key().size()))
continue;
result.emplace_back(it->value().data(), it->value().size());
rocksdb::Status status;
if (m_spbatch)
status = m_spbatch->Delete(m_spexpirecolfamily.get(), it->key());
else
status = m_spdb->Delete(WriteOptions(), m_spexpirecolfamily.get(), it->key());
if (!status.ok())
throw status.ToString();
}
return result;
}
@@ -283,11 +273,11 @@ std::vector<std::string> RocksDBStorageProvider::getEvictionCandidates(unsigned
for (it->Seek(randomHashSlot()); it->Valid() && result.size() < count; it->Next()) {
if (FInternalKey(it->key().data(), it->key().size()))
continue;
result.emplace_back(it->key().data() + HASHSLOT_PREFIX_BYTES, it->key().size() - HASHSLOT_PREFIX_BYTES);
result.emplace_back(it->key().data() + 2, it->key().size() - 2);
}
} else {
std::unique_ptr<rocksdb::Iterator> it = std::unique_ptr<rocksdb::Iterator>(m_spdb->NewIterator(ReadOptions(), m_spexpirecolfamily.get()));
for (it->SeekToFirst(); it->Valid() && result.size() < count; it->Next()) {
for (it->SeekToFirst(); it->Valid() && result.size() < 16; it->Next()) {
if (FInternalKey(it->key().data(), it->key().size()))
continue;
result.emplace_back(it->value().data(), it->value().size());
+1 -13
View File
@@ -4,21 +4,9 @@
#include "../IStorage.h"
#include <rocksdb/db.h>
#include <rocksdb/utilities/write_batch_with_index.h>
#ifdef __APPLE__
#include <libkern/OSByteOrder.h>
#define htole16 OSSwapHostToLittleInt16
#define le16toh OSSwapLittleToHostInt16
#define htobe64 OSSwapHostToBigInt64
#else
#include <endian.h>
#endif
#include "../fastlock.h"
#define INTERNAL_KEY_PREFIX "\x00\x04\x03\x00\x05\x02\x04"
#define HASHSLOT_PREFIX_TYPE uint16_t
#define HASHSLOT_PREFIX_BYTES sizeof(HASHSLOT_PREFIX_TYPE)
#define HASHSLOT_PREFIX_ENDIAN htole16
#define HASHSLOT_PREFIX_RECOVER le16toh
static const char count_key[] = INTERNAL_KEY_PREFIX "__keydb__count\1";
static const char version_key[] = INTERNAL_KEY_PREFIX "__keydb__version\1";
static const char meta_key[] = INTERNAL_KEY_PREFIX "__keydb__metadata\1";
@@ -48,7 +36,7 @@ public:
virtual bool enumerate(callback fn) const override;
virtual bool enumerate_hashslot(callback fn, unsigned int hashslot) const override;
virtual std::vector<std::string> getExpirationCandidates(unsigned int count) override;
virtual std::vector<std::string> getExpirationCandidates(unsigned int count, long long time) override;
virtual std::vector<std::string> getEvictionCandidates(unsigned int count) override;
virtual void setExpire(const char *key, size_t cchKey, long long expire) override;
virtual void removeExpire(const char *key, size_t cchKey, long long expire) override;
+2 -2
View File
@@ -72,7 +72,7 @@ RocksDBStorageFactory::RocksDBStorageFactory(const char *dbfile, int dbnum, cons
rocksdb::DB *db = nullptr;
auto options = RocksDbOptions();
options.prefix_extractor.reset(rocksdb::NewFixedPrefixTransform(HASHSLOT_PREFIX_BYTES));
options.prefix_extractor.reset(rocksdb::NewFixedPrefixTransform(2));
for (int idb = 0; idb < dbnum; ++idb)
{
@@ -196,7 +196,7 @@ IStorage *RocksDBStorageFactory::create(int db, key_load_iterator iter, void *pr
printf("\tDatabase %d was not shutdown cleanly, recomputing metrics\n", db);
fFirstRealKey = false;
if (iter != nullptr)
iter(it->key().data()+HASHSLOT_PREFIX_BYTES, it->key().size()-HASHSLOT_PREFIX_BYTES, privdata);
iter(it->key().data()+2, it->key().size()-2, privdata);
++count;
}
}
+1 -1
View File
@@ -29,7 +29,7 @@ public:
virtual bool enumerate_hashslot(callback fn, unsigned int hashslot) const override;
virtual size_t count() const override;
virtual std::vector<std::string> getExpirationCandidates(unsigned int) override { return std::vector<std::string>(); }
virtual std::vector<std::string> getExpirationCandidates(unsigned int, long long) override { return std::vector<std::string>(); }
virtual std::vector<std::string> getEvictionCandidates(unsigned int) override { return std::vector<std::string>(); }
virtual void setExpire(const char *, size_t, long long) override {}
virtual void removeExpire(const char *, size_t, long long) override {}
+4 -4
View File
@@ -2036,7 +2036,7 @@ struct zsetopsrc {
zset *zs;
zskiplistNode *node;
} sl;
} iterzset;
} zset;
} iter;
};
@@ -2085,7 +2085,7 @@ void zuiInitIterator(zsetopsrc *op) {
/* Sorted sets are traversed in reverse order to optimize for
* the insertion of the elements in a new list as in
* ZDIFF/ZINTER/ZUNION */
iterzset *it = (iterzset*)&op->iter.iterzset;
iterzset *it = (iterzset*)&op->iter.zset;
if (op->encoding == OBJ_ENCODING_ZIPLIST) {
it->zl.zl = (unsigned char*)op->subject->m_ptr;
it->zl.eptr = ziplistIndex(it->zl.zl,-2);
@@ -2118,7 +2118,7 @@ void zuiClearIterator(zsetopsrc *op) {
serverPanic("Unknown set encoding");
}
} else if (op->type == OBJ_ZSET) {
iterzset *it = &op->iter.iterzset;
iterzset *it = &op->iter.zset;
if (op->encoding == OBJ_ENCODING_ZIPLIST) {
UNUSED(it); /* skip */
} else if (op->encoding == OBJ_ENCODING_SKIPLIST) {
@@ -2194,7 +2194,7 @@ int zuiNext(zsetopsrc *op, zsetopval *val) {
serverPanic("Unknown set encoding");
}
} else if (op->type == OBJ_ZSET) {
iterzset *it = &op->iter.iterzset;
iterzset *it = &op->iter.zset;
if (op->encoding == OBJ_ENCODING_ZIPLIST) {
/* No need to check both, but better be explicit. */
if (it->zl.eptr == NULL || it->zl.sptr == NULL)
+15
View File
@@ -81,6 +81,21 @@ if {$::flash_enabled} {
}
}
test { EXPIRE reduces used disk space } {
r flushall
r set testkey foo ex 10
r debug flush-storage
set used [r debug get-storage-usage]
assert_equal {1} [r dbsize]
wait_for_condition 50 1000 {
[r dbsize] == 0
} else {
fail "key is not expired"
}
set after [r debug get-storage-usage]
assert {$after < $used}
}
test { SUBKEY EXPIRE persists after cache flush } {
r flushall
r sadd testkey foo bar baz