Skip to content

Commit

Permalink
Merge branch 'redis:unstable' into unstable
Browse files Browse the repository at this point in the history
  • Loading branch information
dtest11 authored Nov 28, 2023
2 parents cfc2718 + 095d057 commit 5ba2987
Show file tree
Hide file tree
Showing 12 changed files with 117 additions and 49 deletions.
11 changes: 8 additions & 3 deletions src/db.c
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ int getFairRandomSlot(redisDb *db, dbKeyType keyType) {
*
* In this case slot #3 contains key that we are trying to find.
*
* This function is 1 based and the range of the target is [1..dbSize], dbSize inclusive.
* The return value is 0 based slot, and the range of the target is [1..dbSize], dbSize inclusive.
*
* To find the slot, we start with the root node of the binary index tree and search through its children
* from the highest index (2^14 in our case) to the lowest index. At each node, we check if the target
Expand All @@ -547,8 +547,13 @@ int findSlotByKeyIndex(redisDb *db, unsigned long target, dbKeyType keyType) {
result = current;
}
}
/* Unlike BIT, slots are 0-based, so we need to subtract 1, but we also need to add 1,
* since we want the next slot. */
/* Adjust the result to get the correct slot:
* 1. result += 1;
* After the calculations, the index of target in slot_size_index should be the next one,
* so we should add 1.
* 2. result -= 1;
* Unlike BIT(slot_size_index is 1-based), slots are 0-based, so we need to subtract 1.
* As the addition and subtraction cancel each other out, we can simply return the result. */
return result;
}

Expand Down
10 changes: 9 additions & 1 deletion src/expire.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ void activeExpireCycle(int type) {

int j, iteration = 0;
int dbs_per_call = CRON_DBS_PER_CALL;
int dbs_performed = 0;
long long start = ustime(), timelimit, elapsed;

/* If 'expire' action is paused, for whatever reason, then don't expire any key.
Expand Down Expand Up @@ -226,7 +227,12 @@ void activeExpireCycle(int type) {
/* Try to smoke-out bugs (server.also_propagate should be empty here) */
serverAssert(server.also_propagate.numops == 0);

for (j = 0; j < dbs_per_call && timelimit_exit == 0; j++) {
/* Stop iteration when one of the following conditions is met:
*
* 1) We have checked a sufficient number of databases with expiration time.
* 2) The time limit has been exceeded.
* 3) All databases have been traversed. */
for (j = 0; dbs_performed < dbs_per_call && timelimit_exit == 0 && j < server.dbnum; j++) {
/* Scan callback data including expired and checked count per iteration. */
expireScanData data;

Expand All @@ -238,6 +244,8 @@ void activeExpireCycle(int type) {
* distribute the time evenly across DBs. */
current_db++;

if (dbSize(db, DB_EXPIRES)) dbs_performed++;

/* Continue to expire if at the end of the cycle there are still
* a big percentage of keys to expire, compared to the number of keys
* we scanned. The percentage, stored in config_cycle_acceptable_stale
Expand Down
2 changes: 1 addition & 1 deletion src/hyperloglog.c
Original file line number Diff line number Diff line change
Expand Up @@ -1220,10 +1220,10 @@ void pfaddCommand(client *c) {
}
hdr = o->ptr;
if (updated) {
HLL_INVALIDATE_CACHE(hdr);
signalModifiedKey(c,c->db,c->argv[1]);
notifyKeyspaceEvent(NOTIFY_STRING,"pfadd",c->argv[1],c->db->id);
server.dirty += updated;
HLL_INVALIDATE_CACHE(hdr);
}
addReply(c, updated ? shared.cone : shared.czero);
}
Expand Down
33 changes: 15 additions & 18 deletions src/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -12150,6 +12150,19 @@ int parseLoadexArguments(RedisModuleString ***module_argv, int *module_argc) {
return REDISMODULE_OK;
}

/* Unregister module-related things, called when moduleLoad fails or moduleUnload. */
void moduleUnregisterCleanup(RedisModule *module) {
moduleFreeAuthenticatedClients(module);
moduleUnregisterCommands(module);
moduleUnsubscribeNotifications(module);
moduleUnregisterSharedAPI(module);
moduleUnregisterUsedAPI(module);
moduleUnregisterFilters(module);
moduleUnsubscribeAllServerEvents(module);
moduleRemoveConfigs(module);
moduleUnregisterAuthCBs(module);
}

/* Load a module and initialize it. On success C_OK is returned, otherwise
* C_ERR is returned. */
int moduleLoad(const char *path, void **module_argv, int module_argc, int is_loadex) {
Expand Down Expand Up @@ -12184,12 +12197,8 @@ int moduleLoad(const char *path, void **module_argv, int module_argc, int is_loa
serverLog(LL_WARNING,
"Module %s initialization failed. Module not loaded",path);
if (ctx.module) {
moduleUnregisterCommands(ctx.module);
moduleUnregisterSharedAPI(ctx.module);
moduleUnregisterUsedAPI(ctx.module);
moduleUnregisterCleanup(ctx.module);
moduleRemoveCateogires(ctx.module);
moduleRemoveConfigs(ctx.module);
moduleUnregisterAuthCBs(ctx.module);
moduleFreeModuleStructure(ctx.module);
}
moduleFreeContext(&ctx);
Expand Down Expand Up @@ -12230,8 +12239,6 @@ int moduleLoad(const char *path, void **module_argv, int module_argc, int is_loa
}

if (post_load_err) {
/* Unregister module auth callbacks (if any exist) that this Module registered onload. */
moduleUnregisterAuthCBs(ctx.module);
moduleUnload(ctx.module->name, NULL);
moduleFreeContext(&ctx);
return C_ERR;
Expand Down Expand Up @@ -12289,17 +12296,7 @@ int moduleUnload(sds name, const char **errmsg) {
}
}

moduleFreeAuthenticatedClients(module);
moduleUnregisterCommands(module);
moduleUnregisterSharedAPI(module);
moduleUnregisterUsedAPI(module);
moduleUnregisterFilters(module);
moduleUnregisterAuthCBs(module);
moduleRemoveConfigs(module);

/* Remove any notification subscribers this module might have */
moduleUnsubscribeNotifications(module);
moduleUnsubscribeAllServerEvents(module);
moduleUnregisterCleanup(module);

/* Unload the dynamic library. */
if (dlclose(module->handle) == -1) {
Expand Down
26 changes: 12 additions & 14 deletions src/t_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -631,15 +631,14 @@ void lsetCommand(client *c) {

listTypeTryConversionAppend(o,c->argv,3,3,NULL,NULL);
if (listTypeReplaceAtIndex(o,index,value)) {
addReply(c,shared.ok);
signalModifiedKey(c,c->db,c->argv[1]);
notifyKeyspaceEvent(NOTIFY_LIST,"lset",c->argv[1],c->db->id);
server.dirty++;

/* We might replace a big item with a small one or vice versa, but we've
* already handled the growing case in listTypeTryConversionAppend()
* above, so here we just need to try the conversion for shrinking. */
listTypeTryConversion(o,LIST_CONV_SHRINKING,NULL,NULL);
addReply(c,shared.ok);
signalModifiedKey(c,c->db,c->argv[1]);
notifyKeyspaceEvent(NOTIFY_LIST,"lset",c->argv[1],c->db->id);
server.dirty++;
} else {
addReplyErrorObject(c,shared.outofrangeerr);
}
Expand Down Expand Up @@ -1086,15 +1085,14 @@ void lremCommand(client *c) {
listTypeReleaseIterator(li);

if (removed) {
signalModifiedKey(c,c->db,c->argv[1]);
notifyKeyspaceEvent(NOTIFY_LIST,"lrem",c->argv[1],c->db->id);
}

if (listTypeLength(subject) == 0) {
dbDelete(c->db,c->argv[1]);
notifyKeyspaceEvent(NOTIFY_GENERIC,"del",c->argv[1],c->db->id);
} else if (removed) {
listTypeTryConversion(subject,LIST_CONV_SHRINKING,NULL,NULL);
if (listTypeLength(subject) == 0) {
dbDelete(c->db,c->argv[1]);
notifyKeyspaceEvent(NOTIFY_GENERIC,"del",c->argv[1],c->db->id);
} else {
listTypeTryConversion(subject,LIST_CONV_SHRINKING,NULL,NULL);
}
signalModifiedKey(c,c->db,c->argv[1]);
}

addReplyLongLong(c,removed);
Expand All @@ -1107,9 +1105,9 @@ void lmoveHandlePush(client *c, robj *dstkey, robj *dstobj, robj *value,
dstobj = createListListpackObject();
dbAdd(c->db,dstkey,dstobj);
}
signalModifiedKey(c,c->db,dstkey);
listTypeTryConversionAppend(dstobj,&value,0,0,NULL,NULL);
listTypePush(dstobj,value,where);
signalModifiedKey(c,c->db,dstkey);
notifyKeyspaceEvent(NOTIFY_LIST,
where == LIST_HEAD ? "lpush" : "rpush",
dstkey,
Expand Down
2 changes: 1 addition & 1 deletion src/t_zset.c
Original file line number Diff line number Diff line change
Expand Up @@ -4036,7 +4036,6 @@ void genericZpopCommand(client *c, robj **keyv, int keyc, int where, int emitkey
if (result_count == 0) { /* Do this only for the first iteration. */
char *events[2] = {"zpopmin","zpopmax"};
notifyKeyspaceEvent(NOTIFY_ZSET,events[where],key,c->db->id);
signalModifiedKey(c,c->db,key);
}

if (use_nested_array) {
Expand All @@ -4055,6 +4054,7 @@ void genericZpopCommand(client *c, robj **keyv, int keyc, int where, int emitkey
dbDelete(c->db,key);
notifyKeyspaceEvent(NOTIFY_GENERIC,"del",key,c->db->id);
}
signalModifiedKey(c,c->db,key);

if (c->cmd->proc == zmpopCommand) {
/* Always replicate it as ZPOP[MIN|MAX] with COUNT option instead of ZMPOP. */
Expand Down
17 changes: 14 additions & 3 deletions tests/modules/commandfilter.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "redismodule.h"

#include <string.h>
#include <strings.h>

static RedisModuleString *log_key_name;

Expand Down Expand Up @@ -92,7 +93,7 @@ int CommandFilter_LogCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int
return REDISMODULE_OK;
}

int CommandFilter_UnfilteredClientdId(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
int CommandFilter_UnfilteredClientId(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
{
if (argc < 2)
return RedisModule_WrongArity(ctx);
Expand Down Expand Up @@ -192,7 +193,7 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
if (RedisModule_Init(ctx,"commandfilter",1,REDISMODULE_APIVER_1)
== REDISMODULE_ERR) return REDISMODULE_ERR;

if (argc != 2) {
if (argc != 2 && argc != 3) {
RedisModule_Log(ctx, "warning", "Log key name not specified");
return REDISMODULE_ERR;
}
Expand All @@ -219,7 +220,7 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
return REDISMODULE_ERR;

if (RedisModule_CreateCommand(ctx, unfiltered_clientid_name,
CommandFilter_UnfilteredClientdId, "admin", 1,1,1) == REDISMODULE_ERR)
CommandFilter_UnfilteredClientId, "admin", 1,1,1) == REDISMODULE_ERR)
return REDISMODULE_ERR;

if ((filter = RedisModule_RegisterCommandFilter(ctx, CommandFilter_CommandFilter,
Expand All @@ -229,6 +230,16 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
if ((filter1 = RedisModule_RegisterCommandFilter(ctx, CommandFilter_BlmoveSwap, 0)) == NULL)
return REDISMODULE_ERR;

if (argc == 3) {
const char *ptr = RedisModule_StringPtrLen(argv[2], NULL);
if (!strcasecmp(ptr, "noload")) {
/* This is a hint that we return ERR at the last moment of OnLoad. */
RedisModule_FreeString(ctx, log_key_name);
if (retained) RedisModule_FreeString(NULL, retained);
return REDISMODULE_ERR;
}
}

return REDISMODULE_OK;
}

Expand Down
16 changes: 13 additions & 3 deletions tests/modules/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "redismodule.h"
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <assert.h>

/* We need to store events to be able to test and see what we got, and we can't
Expand Down Expand Up @@ -407,9 +408,6 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
return REDISMODULE_ERR; \
}

REDISMODULE_NOT_USED(argv);
REDISMODULE_NOT_USED(argc);

if (RedisModule_Init(ctx,"testhook",1,REDISMODULE_APIVER_1)
== REDISMODULE_ERR) return REDISMODULE_ERR;

Expand Down Expand Up @@ -471,6 +469,18 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
if (RedisModule_CreateCommand(ctx,"hooks.pexpireat", cmdKeyExpiry,"",0,0,0) == REDISMODULE_ERR)
return REDISMODULE_ERR;

if (argc == 1) {
const char *ptr = RedisModule_StringPtrLen(argv[0], NULL);
if (!strcasecmp(ptr, "noload")) {
/* This is a hint that we return ERR at the last moment of OnLoad. */
RedisModule_FreeDict(ctx, event_log);
RedisModule_FreeDict(ctx, removed_event_log);
RedisModule_FreeDict(ctx, removed_subevent_type);
RedisModule_FreeDict(ctx, removed_expiry_log);
return REDISMODULE_ERR;
}
}

return REDISMODULE_OK;
}

Expand Down
14 changes: 11 additions & 3 deletions tests/modules/keyspace_events.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "redismodule.h"
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>

ustime_t cached_time = 0;
Expand Down Expand Up @@ -318,9 +319,6 @@ static int cmdGetDels(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
/* This function must be present on each Redis module. It is used in order to
* register the commands into the Redis server. */
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
REDISMODULE_NOT_USED(argv);
REDISMODULE_NOT_USED(argc);

if (RedisModule_Init(ctx,"testkeyspace",1,REDISMODULE_APIVER_1) == REDISMODULE_ERR){
return REDISMODULE_ERR;
}
Expand Down Expand Up @@ -405,6 +403,16 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
return REDISMODULE_ERR;
}

if (argc == 1) {
const char *ptr = RedisModule_StringPtrLen(argv[0], NULL);
if (!strcasecmp(ptr, "noload")) {
/* This is a hint that we return ERR at the last moment of OnLoad. */
RedisModule_FreeDict(ctx, loaded_event_log);
RedisModule_FreeDict(ctx, module_event_log);
return REDISMODULE_ERR;
}
}

return REDISMODULE_OK;
}

Expand Down
14 changes: 12 additions & 2 deletions tests/unit/moduleapi/commandfilter.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ start_server {tags {"modules"}} {
test "Unload the module - commandfilter" {
assert_equal {OK} [r module unload commandfilter]
}
}
}

test {RM_CommandFilterArgInsert and script argv caching} {
# coverage for scripts calling commands that expand the argv array
Expand Down Expand Up @@ -162,4 +162,14 @@ test {Filtering based on client id} {

$rr close
}
}
}

start_server {} {
test {OnLoad failure will handle un-registration} {
catch {r module load $testmodule log-key 0 noload}
r set mykey @log
assert_equal [r lrange log-key 0 -1] {}
r rpush mylist elem1 @delme elem2
assert_equal [r lrange mylist 0 -1] {elem1 @delme elem2}
}
}
8 changes: 8 additions & 0 deletions tests/unit/moduleapi/hooks.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -310,4 +310,12 @@ tags "modules" {
assert_equal [string match {*module-event-shutdown*} [exec tail -5 < $replica_stdout]] 1
}
}

start_server {} {
test {OnLoad failure will handle un-registration} {
catch {r module load $testmodule noload}
r flushall
r ping
}
}
}
13 changes: 13 additions & 0 deletions tests/unit/moduleapi/keyspace_events.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,17 @@ tags "modules" {
assert_equal {OK} [r set x 1 EX 1]
}
}

start_server {} {
test {OnLoad failure will handle un-registration} {
catch {r module load $testmodule noload}
r set x 1
r hset y f v
r lpush z 1 2 3
r sadd p 1 2 3
r zadd t 1 f1 2 f2
r xadd s * f v
r ping
}
}
}

0 comments on commit 5ba2987

Please sign in to comment.