mirror of https://mirror.osredm.com/root/redis.git
Add API RedisModule_ClusterKeySlot and RedisModule_ClusterCanonicalKeyNameInSlot (#13069)
Sometimes it's useful to compute a key's cluster slot in a module. This API function is just like the command CLUSTER KEYSLOT (but faster). A "reverse" API is also added: `RedisModule_ClusterCanonicalKeyNameInSlot`. Given a slot, it returns a short string that we can call a canonical key for the slot.
This commit is contained in:
parent
9c065c417d
commit
9efc6ad6a6
16
src/module.c
16
src/module.c
|
@ -59,6 +59,7 @@
|
|||
#include "script.h"
|
||||
#include "call_reply.h"
|
||||
#include "hdr_histogram.h"
|
||||
#include "crc16_slottable.h"
|
||||
#include <dlfcn.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
@ -9107,6 +9108,19 @@ void RM_SetClusterFlags(RedisModuleCtx *ctx, uint64_t flags) {
|
|||
server.cluster_module_flags |= CLUSTER_MODULE_FLAG_NO_REDIRECTION;
|
||||
}
|
||||
|
||||
/* Returns the cluster slot of a key, similar to the `CLUSTER KEYSLOT` command.
|
||||
* This function works even if cluster mode is not enabled. */
|
||||
unsigned int RM_ClusterKeySlot(RedisModuleString *key) {
|
||||
return keyHashSlot(key->ptr, sdslen(key->ptr));
|
||||
}
|
||||
|
||||
/* Returns a short string that can be used as a key or as a hash tag in a key,
|
||||
* such that the key maps to the given cluster slot. Returns NULL if slot is not
|
||||
* a valid slot. */
|
||||
const char *RM_ClusterCanonicalKeyNameInSlot(unsigned int slot) {
|
||||
return (slot < CLUSTER_SLOTS) ? crc16_slot_table[slot] : NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* ## Modules Timers API
|
||||
*
|
||||
|
@ -13844,6 +13858,8 @@ void moduleRegisterCoreAPI(void) {
|
|||
REGISTER_API(SetDisconnectCallback);
|
||||
REGISTER_API(GetBlockedClientHandle);
|
||||
REGISTER_API(SetClusterFlags);
|
||||
REGISTER_API(ClusterKeySlot);
|
||||
REGISTER_API(ClusterCanonicalKeyNameInSlot);
|
||||
REGISTER_API(CreateDict);
|
||||
REGISTER_API(FreeDict);
|
||||
REGISTER_API(DictSize);
|
||||
|
|
|
@ -1253,6 +1253,8 @@ REDISMODULE_API void (*RedisModule_GetRandomBytes)(unsigned char *dst, size_t le
|
|||
REDISMODULE_API void (*RedisModule_GetRandomHexChars)(char *dst, size_t len) REDISMODULE_ATTR;
|
||||
REDISMODULE_API void (*RedisModule_SetDisconnectCallback)(RedisModuleBlockedClient *bc, RedisModuleDisconnectFunc callback) REDISMODULE_ATTR;
|
||||
REDISMODULE_API void (*RedisModule_SetClusterFlags)(RedisModuleCtx *ctx, uint64_t flags) REDISMODULE_ATTR;
|
||||
REDISMODULE_API unsigned int (*RedisModule_ClusterKeySlot)(RedisModuleString *key) REDISMODULE_ATTR;
|
||||
REDISMODULE_API const char *(*RedisModule_ClusterCanonicalKeyNameInSlot)(unsigned int slot) REDISMODULE_ATTR;
|
||||
REDISMODULE_API int (*RedisModule_ExportSharedAPI)(RedisModuleCtx *ctx, const char *apiname, void *func) REDISMODULE_ATTR;
|
||||
REDISMODULE_API void * (*RedisModule_GetSharedAPI)(RedisModuleCtx *ctx, const char *apiname) REDISMODULE_ATTR;
|
||||
REDISMODULE_API RedisModuleCommandFilter * (*RedisModule_RegisterCommandFilter)(RedisModuleCtx *ctx, RedisModuleCommandFilterFunc cb, int flags) REDISMODULE_ATTR;
|
||||
|
@ -1617,6 +1619,8 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
|
|||
REDISMODULE_GET_API(GetRandomBytes);
|
||||
REDISMODULE_GET_API(GetRandomHexChars);
|
||||
REDISMODULE_GET_API(SetClusterFlags);
|
||||
REDISMODULE_GET_API(ClusterKeySlot);
|
||||
REDISMODULE_GET_API(ClusterCanonicalKeyNameInSlot);
|
||||
REDISMODULE_GET_API(ExportSharedAPI);
|
||||
REDISMODULE_GET_API(GetSharedAPI);
|
||||
REDISMODULE_GET_API(RegisterCommandFilter);
|
||||
|
|
|
@ -524,6 +524,22 @@ int test_malloc_api(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
|
|||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
int test_keyslot(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
|
||||
/* Static check of the ClusterKeySlot + ClusterCanonicalKeyNameInSlot
|
||||
* round-trip for all slots. */
|
||||
for (unsigned int slot = 0; slot < 16384; slot++) {
|
||||
const char *tag = RedisModule_ClusterCanonicalKeyNameInSlot(slot);
|
||||
RedisModuleString *key = RedisModule_CreateStringPrintf(ctx, "x{%s}y", tag);
|
||||
assert(slot == RedisModule_ClusterKeySlot(key));
|
||||
RedisModule_FreeString(ctx, key);
|
||||
}
|
||||
if (argc != 2){
|
||||
return RedisModule_WrongArity(ctx);
|
||||
}
|
||||
unsigned int slot = RedisModule_ClusterKeySlot(argv[1]);
|
||||
return RedisModule_ReplyWithLongLong(ctx, slot);
|
||||
}
|
||||
|
||||
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
|
||||
REDISMODULE_NOT_USED(argv);
|
||||
REDISMODULE_NOT_USED(argc);
|
||||
|
@ -589,6 +605,8 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
|||
return REDISMODULE_ERR;
|
||||
if (RedisModule_CreateCommand(ctx, "test.malloc_api", test_malloc_api,"", 0, 0, 0) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
if (RedisModule_CreateCommand(ctx, "test.keyslot", test_keyslot, "", 0, 0, 0) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
|
|
@ -497,6 +497,10 @@ start_server {overrides {save {900 1}} tags {"modules"}} {
|
|||
test "malloc API" {
|
||||
assert_equal {OK} [r test.malloc_api 0]
|
||||
}
|
||||
|
||||
test "Cluster keyslot" {
|
||||
assert_equal 12182 [r test.keyslot foo]
|
||||
}
|
||||
}
|
||||
|
||||
start_server {tags {"modules"}} {
|
||||
|
|
Loading…
Reference in New Issue