summaryrefslogtreecommitdiff
path: root/examples/redis-unstable/tests/modules/test_keymeta.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/redis-unstable/tests/modules/test_keymeta.c')
-rw-r--r--examples/redis-unstable/tests/modules/test_keymeta.c585
1 files changed, 0 insertions, 585 deletions
diff --git a/examples/redis-unstable/tests/modules/test_keymeta.c b/examples/redis-unstable/tests/modules/test_keymeta.c
deleted file mode 100644
index ca5d622..0000000
--- a/examples/redis-unstable/tests/modules/test_keymeta.c
+++ /dev/null
@@ -1,585 +0,0 @@
-/* An example module for attaching metadata to keys.
- *
- * This example lets tests create metadata-key classes and then SET and GET metadata
- * to keys. The 8-byte slot stores a handle to a module-managed allocation; here
- * we use to attach a string per-key.
- *
- * The module pre-registers several metadata classes during initialization and exposes
- * the following commands (via RedisModule_CreateCommand):
- *
- * 1) KEYMETA.REGISTER <4-char-id> <version> [FLAGS]
- * Register a new metadata-key class during module load.
- * Returns the <keymeta-class-id> index (Returned from RedisModule_CreateKeyMetaClass)
- * On failure, returns nil
- * In a real module it should be registered "automatically" via OnLoad.
- *
- * FLAGS (colon-separated):
- * KEEPONCOPY - Keep metadata on COPY operation
- * KEEPONRENAME - Keep metadata on RENAME operation
- * KEEPONMOVE - Keep metadata on MOVE operation
- * UNLINKFREE - Use unlink callback for async free
- * RDBLOAD - Enable rdb_load callback (metadata can be loaded from RDB)
- * RDBSAVE - Enable rdb_save callback (metadata can be saved to RDB)
- * ALLOWIGNORE - Enable ALLOW_IGNORE flag (graceful discard on load if
- * class not registered or no rdb_load callback)
- *
- * Example: > keymeta.register KMT1 1 KEEPONCOPY:KEEPONRENAME:ALLOWIGNORE:RDBLOAD:RDBSAVE
- * Example: > keymeta.register KMT2 1 ALLOWIGNORE
- *
- * 2) KEYMETA.SET <4-char-id> <key> <string-value>
- * Set the string value as metadata to given key.
- * Note:
- * - If already set earlier, then it is expected that it will released before setting a
- * new string. That is why this command should start with trying to get first
- * metadata for given key.
- *
- * 3) KEYMETA.GET <4-char-id> <key>
- * Get the metadata attached to the key for the given class.
- * Returns a string attached to the given key. Or nil if nothing is attached.
- *
- * 4) KEYMETA.UNREGISTER <4-char-id>
- * This will mark the key metadata class as released. It can later be reused again
- * by the same class (consider comment above).
- * Return REDISMODULE_OK/REDISMODULE_ERR.
- *
- * 5) KEYMETA.ACTIVE
- * Return total number of active metadata at the moment.
- */
-
-#include "redismodule.h"
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-/* Virtualize class IDs for testing. Values: 0 unused, 1..7 used, -1 released */
-RedisModuleKeyMetaClassId class_ids[8] = { 0 };
-
-/* Mapping from 4-char-id to class-id */
-typedef struct {
- char name[5]; /* 4 chars + null terminator */
- RedisModuleKeyMetaClassId class_id;
-} ClassMapping;
-
-#define MAX_CLASS_MAPPINGS 8
-static ClassMapping class_mappings[MAX_CLASS_MAPPINGS];
-static int num_class_mappings = 0;
-
-/* Reverse lookup: given a class_id, find the 4-char-id name */
-static const char* lookupClassName(RedisModuleKeyMetaClassId class_id) {
- for (int i = 0; i < num_class_mappings; i++) {
- if (class_mappings[i].class_id == class_id) {
- return class_mappings[i].name;
- }
- }
- return NULL;
-}
-
-/* Track active metadata instances (not yet freed) */
-static long long active_metadata_count = 0;
-
-/* Helper functions for class mapping */
-
-/* Add a mapping from 4-char-id to class-id */
-static int addClassMapping(const char *name, RedisModuleKeyMetaClassId class_id) {
- if (num_class_mappings >= MAX_CLASS_MAPPINGS) {
- return 0; /* No space */
- }
- strncpy(class_mappings[num_class_mappings].name, name, 4);
- class_mappings[num_class_mappings].name[4] = '\0';
- class_mappings[num_class_mappings].class_id = class_id;
- num_class_mappings++;
- return 1;
-}
-
-/* Lookup class-id by 4-char-id. Returns -1 if not found. */
-static RedisModuleKeyMetaClassId lookupClassId(const char *name) {
- for (int i = 0; i < num_class_mappings; i++) {
- if (strncmp(class_mappings[i].name, name, 4) == 0) {
- return class_mappings[i].class_id;
- }
- }
- return -1;
-}
-
-/* Remove a mapping by 4-char-id */
-static int removeClassMapping(const char *name) {
- for (int i = 0; i < num_class_mappings; i++) {
- if (strncmp(class_mappings[i].name, name, 4) == 0) {
- /* Shift remaining entries down */
- for (int j = i; j < num_class_mappings - 1; j++) {
- class_mappings[j] = class_mappings[j + 1];
- }
- num_class_mappings--;
- return 1;
- }
- }
- return 0;
-}
-
-/* Callback functions for metadata lifecycle */
-
-/* Copy callback - called when a key is copied */
-static int KeyMetaCopyCallback(RedisModuleKeyOptCtx *ctx, uint64_t *meta) {
- REDISMODULE_NOT_USED(ctx);
- char *str = (char *)*meta;
- /* Note, condition is redundant since cb only invoked when meta != reset_value */
- if (str) {
- char *new_str = strdup(str);
- *meta = (uint64_t)new_str;
- active_metadata_count++; /* New metadata instance created */
- }
- return 1; /* Keep metadata */
-}
-
-/* Rename callback - called when a key is renamed. */
-static int KeyMetaRenameDiscardCallback(RedisModuleKeyOptCtx *ctx, uint64_t *meta) {
- REDISMODULE_NOT_USED(ctx);
- REDISMODULE_NOT_USED(meta);
- return 0;
-}
-
-/* Unlink callback - called when a key is unlinked */
-static void KeyMetaUnlinkCallback(RedisModuleKeyOptCtx *ctx, uint64_t *meta) {
- /* Let's challenge and free early on before free callback */
- /* Note, condition is redundant since cb only invoked when meta != reset_value */
- if (*meta != 0) {
- char *str = (char *)*meta;
- free(str);
- *meta = 0; /* Set to reset_value !!! */
- active_metadata_count--; /* Metadata instance freed */
- }
- REDISMODULE_NOT_USED(ctx);
-}
-
-/* Free callback - called when metadata needs to be freed */
-static void KeyMetaFreeCallback(const char *keyname, uint64_t meta) {
- REDISMODULE_NOT_USED(keyname);
- /* Note, condition is redundant since cb only invoked when meta != reset_value */
- if (meta != 0) {
- char *str = (char *)meta;
- free(str);
- active_metadata_count--; /* Metadata instance freed */
- }
-}
-
-static int KeyMetaMoveDiscardCallback(RedisModuleKeyOptCtx *ctx, uint64_t *meta) {
- REDISMODULE_NOT_USED(ctx);
- REDISMODULE_NOT_USED(meta);
- return 0; /* discard metadata */
-}
-
-/* RDB Save Callback - Serialize metadata to RDB
- * This callback is invoked during RDB save to write the metadata value.
- *
- * Parameters:
- * - rdb: RedisModuleIO context for writing to RDB
- * - value: The kvobj (key-value object) - not used in this implementation
- * - meta: Pointer to the 8-byte metadata value (pointer to our string)
- */
-static void KeyMetaRDBSaveCallback(RedisModuleIO *rdb, void *value, uint64_t *meta) {
- REDISMODULE_NOT_USED(value);
-
- /* If metadata is NULL (reset_value), don't save anything */
- if (*meta == 0) return;
-
- /* Extract the string from the metadata pointer */
- char *metadata_string = (char *)*meta;
-
- /* Save the string to RDB using SaveStringBuffer */
- RedisModule_SaveStringBuffer(rdb, metadata_string, strlen(metadata_string));
- /* Save more silly data */
- RedisModule_SaveSigned(rdb, 1);
- RedisModule_SaveFloat(rdb, 1.5);
- RedisModule_SaveLongDouble(rdb, 0.333333333333333333L);
-}
-
-/* RDB Load Callback - Deserialize metadata from RDB
- * This callback is invoked during RDB load to read the metadata value.
- *
- * Parameters:
- * - rdb: RedisModuleIO context for reading from RDB
- * - meta: Pointer to store the loaded 8-byte metadata value
- * - encver: Encoding version (class version from RDB)
- *
- * Returns:
- * - 1: Attach metadata to key (success)
- * - 0: Ignore/skip metadata (not an error)
- * - -1: Error - abort RDB load
- */
-static int KeyMetaRDBLoadCallback(RedisModuleIO *rdb, uint64_t *meta, int encver) {
- REDISMODULE_NOT_USED(encver);
-
- /* Load the string from RDB using LoadStringBuffer */
- size_t len;
- char *loaded_string = RedisModule_LoadStringBuffer(rdb, &len);
-
- if (loaded_string == NULL) {
- /* Error loading string */
- return -1;
- }
-
- /* Allocate and copy the string (LoadStringBuffer returns a buffer that must be freed) */
- char *metadata_string = malloc(len + 1);
- if (metadata_string == NULL) {
- RedisModule_Free(loaded_string);
- return -1;
- }
-
- memcpy(metadata_string, loaded_string, len);
- metadata_string[len] = '\0';
- RedisModule_Free(loaded_string);
-
- /* Load the additional data that was saved (must match rdb_save) */
- int64_t signed_val = RedisModule_LoadSigned(rdb);
- float float_val = RedisModule_LoadFloat(rdb);
- long double ldouble_val = RedisModule_LoadLongDouble(rdb);
- /* We don't use these values, just need to consume them from the stream */
- (void)signed_val;
- (void)float_val;
- (void)ldouble_val;
-
- /* Store the pointer in metadata */
- *meta = (uint64_t)metadata_string;
- active_metadata_count++; /* New metadata instance created */
-
- /* Return 1 to attach metadata to the key */
- return 1;
-}
-
-/* AOF Rewrite Callback - Common implementation for all classes
- * This callback is invoked during AOF rewrite to emit commands that will
- * recreate the metadata when the AOF is loaded.
- *
- * Parameters:
- * - aof: RedisModuleIO context for writing to AOF
- * - value: The kvobj (key-value object) - not used in this implementation
- * - meta: The 8-byte metadata value (pointer to our string)
- * - class_id: The class ID for this metadata
- */
-static void KeyMetaAOFRewriteCallback_Class(RedisModuleIO *aof, void *value, uint64_t meta, RedisModuleKeyMetaClassId class_id) {
- REDISMODULE_NOT_USED(value);
-
- /* If metadata is NULL (reset_value), don't emit anything */
- if (meta == 0) return;
-
- /* Extract the string from the metadata pointer */
- char *metadata_string = (char *)meta;
-
- /* Lookup the 9-byte-id name for this class */
- const char *class_name = lookupClassName(class_id);
- if (!class_name) {
- /* This shouldn't happen, but handle gracefully */
- return;
- }
-
- /* Get the key name from the AOF IO context */
- const RedisModuleString *key = RedisModule_GetKeyNameFromIO(aof);
- if (!key) {
- /* Key name not available - shouldn't happen during AOF rewrite */
- return;
- }
-
- /* Emit the KEYMETA.SET command to recreate this metadata
- * Format: KEYMETA.SET <9-byte-id> <key> <string-value> */
- RedisModule_EmitAOF(aof, "KEYMETA.SET", "csc",
- class_name, /* c: 9-byte-id (C string) */
- key, /* s: key name (RedisModuleString) */
- metadata_string); /* c: metadata value (C string) */
-}
-
-/* Individual AOF rewrite callbacks for each class (1-7)
- * Each callback wraps the common implementation with its specific class ID */
-static void KeyMetaAOFRewriteCb1(RedisModuleIO *aof, void *value, uint64_t meta) {
- KeyMetaAOFRewriteCallback_Class(aof, value, meta, 1);
-}
-
-static void KeyMetaAOFRewriteCb2(RedisModuleIO *aof, void *value, uint64_t meta) {
- KeyMetaAOFRewriteCallback_Class(aof, value, meta, 2);
-}
-
-static void KeyMetaAOFRewriteCb3(RedisModuleIO *aof, void *value, uint64_t meta) {
- KeyMetaAOFRewriteCallback_Class(aof, value, meta, 3);
-}
-
-static void KeyMetaAOFRewriteCb4(RedisModuleIO *aof, void *value, uint64_t meta) {
- KeyMetaAOFRewriteCallback_Class(aof, value, meta, 4);
-}
-
-static void KeyMetaAOFRewriteCb5(RedisModuleIO *aof, void *value, uint64_t meta) {
- KeyMetaAOFRewriteCallback_Class(aof, value, meta, 5);
-}
-
-static void KeyMetaAOFRewriteCb6(RedisModuleIO *aof, void *value, uint64_t meta) {
- KeyMetaAOFRewriteCallback_Class(aof, value, meta, 6);
-}
-
-static void KeyMetaAOFRewriteCb7(RedisModuleIO *aof, void *value, uint64_t meta) {
- KeyMetaAOFRewriteCallback_Class(aof, value, meta, 7);
-}
-
-/* KEYMETA.REGISTER <4-char-id> <version> [KEEPONCOPY:KEEPONRENAME:UNLINKFREE:ALLOWIGNORE:NORDBLOAD:NORDBSAVE] */
-static int KeyMetaRegister_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
- if (argc < 3 || argc > 4) {
- return RedisModule_WrongArity(ctx);
- }
-
- /* argv[1]: key metadata class name */
- size_t namelen;
- const char *metaname = RedisModule_StringPtrLen(argv[1], &namelen);
-
- /* argv[2]: key metadata class version */
- long long metaver;
- if (RedisModule_StringToLongLong(argv[2], &metaver) != REDISMODULE_OK) {
- RedisModule_ReplyWithError(ctx, "ERR invalid version number");
- return REDISMODULE_OK;
- }
-
- /* Parse optional callback flags */
- int keep_on_copy = 0, keep_on_rename = 0, unlink_free = 0, keep_on_move = 0;
- int allow_ignore = 0; /* Default: ALLOW_IGNORE disabled */
- int rdb_load = 0; /* Default: rdb_load disabled */
- int rdb_save = 0; /* Default: rdb_save disabled */
-
- if (argc == 4) {
- const char *flags = RedisModule_StringPtrLen(argv[3], NULL);
- if (strstr(flags, "KEEPONCOPY")) keep_on_copy = 1;
- if (strstr(flags, "KEEPONRENAME")) keep_on_rename = 1;
- if (strstr(flags, "UNLINKFREE")) unlink_free = 1;
- if (strstr(flags, "KEEPONMOVE")) keep_on_move = 1;
- if (strstr(flags, "ALLOWIGNORE")) allow_ignore = 1; /* Enable ALLOW_IGNORE */
- if (strstr(flags, "RDBLOAD")) rdb_load = 1; /* Enable rdb_load */
- if (strstr(flags, "RDBSAVE")) rdb_save = 1; /* Enable rdb_save */
- }
-
- /* Setup configuration */
- RedisModuleKeyMetaClassConfig config = {0};
- config.version = REDISMODULE_KEY_META_VERSION;
- config.flags = allow_ignore ? (1 << REDISMODULE_META_ALLOW_IGNORE) : 0;
- config.reset_value = (uint64_t)NULL; /* NULL pointer means no resource to free */
- config.rdb_load = rdb_load ? KeyMetaRDBLoadCallback : NULL;
- config.rdb_save = rdb_save ? KeyMetaRDBSaveCallback : NULL;
- switch (num_class_mappings + 1) { /* distinct cb per class */
- case 1: config.aof_rewrite = KeyMetaAOFRewriteCb1; break;
- case 2: config.aof_rewrite = KeyMetaAOFRewriteCb2; break;
- case 3: config.aof_rewrite = KeyMetaAOFRewriteCb3; break;
- case 4: config.aof_rewrite = KeyMetaAOFRewriteCb4; break;
- case 5: config.aof_rewrite = KeyMetaAOFRewriteCb5; break;
- case 6: config.aof_rewrite = KeyMetaAOFRewriteCb6; break;
- case 7: config.aof_rewrite = KeyMetaAOFRewriteCb7; break;
- default: config.aof_rewrite = NULL; break;
- }
- config.free = KeyMetaFreeCallback;
- config.copy = keep_on_copy ? KeyMetaCopyCallback : NULL;
- config.rename = keep_on_rename ? NULL : KeyMetaRenameDiscardCallback;
- config.move = keep_on_move ? NULL : KeyMetaMoveDiscardCallback;
- config.defrag = NULL;
- config.unlink = unlink_free ? KeyMetaUnlinkCallback : NULL;
- config.mem_usage = NULL;
- config.free_effort = NULL;
-
- /* Create the metadata class */
- RedisModuleKeyMetaClassId class_id = RedisModule_CreateKeyMetaClass(ctx, metaname, (int)metaver, &config);
-
- if (class_id < 0) {
- RedisModule_ReplyWithError(ctx, "ERR failed to create metadata class");
- return REDISMODULE_OK;
- } else {
- /* Store the mapping from 9-byte-id to class-id */
- if (!addClassMapping(metaname, class_id)) {
- RedisModule_ReplyWithError(ctx, "ERR failed to store class mapping");
- return REDISMODULE_OK;
- }
- RedisModule_ReplyWithLongLong(ctx, class_id);
- }
-
- return REDISMODULE_OK;
-}
-
-/* KEYMETA.SET <9-byte-id> <key> <string-value> */
-static int KeyMetaSet_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
- if (argc != 4) {
- return RedisModule_WrongArity(ctx);
- }
-
- /* Parse arguments */
- const char *metaname = RedisModule_StringPtrLen(argv[1], NULL);
- RedisModuleString *keyname = argv[2];
- const char *value = RedisModule_StringPtrLen(argv[3], NULL);
-
- /* Lookup the metadata class by name */
- RedisModuleKeyMetaClassId class_id = lookupClassId(metaname);
- if (class_id < 0) {
- RedisModule_ReplyWithError(ctx, "ERR metadata class not found");
- return REDISMODULE_OK;
- }
-
- /* Open the key for writing */
- RedisModuleKey *key = RedisModule_OpenKey(ctx, keyname, REDISMODULE_READ | REDISMODULE_WRITE);
-
- if (RedisModule_KeyType(key) == REDISMODULE_KEYTYPE_EMPTY) {
- RedisModule_ReplyWithNull(ctx);
- RedisModule_CloseKey(key);
- return REDISMODULE_OK;
- }
-
- /* Check if metadata already exists and free it first.
- *
- * Note: The caller is responsible for retrieving and freeing any existing
- * pointer-based metadata before RM_SetKeyMeta() to a new value
- */
- uint64_t meta = 0;
- if (RedisModule_GetKeyMeta(class_id, key, &meta) == REDISMODULE_OK) {
- if (meta != 0) {
- free((char *)meta);
- active_metadata_count--; /* Old metadata freed */
- }
- }
-
- char *new_str = strdup(value);
- int res = RedisModule_SetKeyMeta(class_id, key, (uint64_t)new_str);
-
- if (res == REDISMODULE_OK) {
- active_metadata_count++; /* New metadata instance created */
- }
-
- RedisModule_CloseKey(key);
-
- if (res == REDISMODULE_OK) {
- RedisModule_ReplyWithSimpleString(ctx, "OK");
- } else {
- free(new_str);
- RedisModule_ReplyWithError(ctx, "ERR failed to set metadata");
- }
- return REDISMODULE_OK;
-}
-
-/* KEYMETA.GET <9-byte-id> <key> */
-static int KeyMetaGet_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
- if (argc != 3) {
- return RedisModule_WrongArity(ctx);
- }
-
- /* Parse arguments */
- const char *metaname = RedisModule_StringPtrLen(argv[1], NULL);
- RedisModuleString *keyname = argv[2];
-
- /* Lookup the metadata class by name */
- RedisModuleKeyMetaClassId class_id = lookupClassId(metaname);
- if (class_id < 0) {
- RedisModule_ReplyWithError(ctx, "ERR metadata class not found");
- return REDISMODULE_OK;
- }
-
- /* Open the key for reading */
- RedisModuleKey *key = RedisModule_OpenKey(ctx, keyname, REDISMODULE_READ);
- if (RedisModule_KeyType(key) == REDISMODULE_KEYTYPE_EMPTY) {
- RedisModule_ReplyWithNull(ctx);
- RedisModule_CloseKey(key);
- return REDISMODULE_OK;
- }
-
- /* Get the metadata */
- uint64_t meta = 0;
- int result = RedisModule_GetKeyMeta(class_id, key, &meta);
-
- RedisModule_CloseKey(key);
-
- if (result == REDISMODULE_OK && meta != 0) {
- char *str = (char *)meta;
- RedisModule_ReplyWithCString(ctx, str);
- } else {
- RedisModule_ReplyWithNull(ctx);
- }
-
- return REDISMODULE_OK;
-}
-
-/* KEYMETA.UNREGISTER <9-byte-id> */
-static int KeyMetaUnregister_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
- if (argc != 2) {
- return RedisModule_WrongArity(ctx);
- }
-
- /* Parse arguments */
- const char *metaname = RedisModule_StringPtrLen(argv[1], NULL);
-
- /* Lookup the metadata class by name */
- RedisModuleKeyMetaClassId class_id = lookupClassId(metaname);
- if (class_id < 0) {
- RedisModule_ReplyWithError(ctx, "ERR metadata class not found");
- return REDISMODULE_OK;
- }
-
- /* Release the metadata class */
- int result = RedisModule_ReleaseKeyMetaClass(class_id);
-
- if (result == REDISMODULE_OK) {
- /* Remove the mapping */
- removeClassMapping(metaname);
- RedisModule_ReplyWithSimpleString(ctx, "OK");
- } else {
- RedisModule_ReplyWithError(ctx, "ERR failed to unregister class");
- }
- return REDISMODULE_OK;
-}
-
-/* KEYMETA.ACTIVE
- * Returns the total number of active metadata instances that haven't been freed yet.
- * This is useful for testing to verify that metadata is properly cleaned up. */
-static int KeyMetaActive_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
- if (argc != 1) {
- return RedisModule_WrongArity(ctx);
- }
- REDISMODULE_NOT_USED(argv);
-
- RedisModule_ReplyWithLongLong(ctx, active_metadata_count);
- return REDISMODULE_OK;
-}
-
-/* Module initialization */
-int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
- REDISMODULE_NOT_USED(argv);
- REDISMODULE_NOT_USED(argc);
-
- if (RedisModule_Init(ctx, "test_metakey", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR) {
- return REDISMODULE_ERR;
- }
-
- /* Register commands */
- if (RedisModule_CreateCommand(ctx, "keymeta.register",
- KeyMetaRegister_RedisCommand, "write", 0, 0, 0) == REDISMODULE_ERR) {
- return REDISMODULE_ERR;
- }
-
- if (RedisModule_CreateCommand(ctx, "keymeta.set",
- KeyMetaSet_RedisCommand, "write deny-oom", 1, 1, 1) == REDISMODULE_ERR) {
- return REDISMODULE_ERR;
- }
-
- if (RedisModule_CreateCommand(ctx, "keymeta.get",
- KeyMetaGet_RedisCommand, "readonly", 1, 1, 1) == REDISMODULE_ERR) {
- return REDISMODULE_ERR;
- }
-
- if (RedisModule_CreateCommand(ctx, "keymeta.unregister",
- KeyMetaUnregister_RedisCommand, "write", 0, 0, 0) == REDISMODULE_ERR) {
- return REDISMODULE_ERR;
- }
-
- if (RedisModule_CreateCommand(ctx, "keymeta.active",
- KeyMetaActive_RedisCommand, "readonly fast", 0, 0, 0) == REDISMODULE_ERR) {
- return REDISMODULE_ERR;
- }
-
- return REDISMODULE_OK;
-}
-
-int RedisModule_OnUnload(RedisModuleCtx *ctx) {
- REDISMODULE_NOT_USED(ctx);
- long unsigned int i;
- for (i = 0 ; i < sizeof(class_ids) / sizeof(class_ids[0]); i++) {
- if (class_ids[i] > 0)
- RedisModule_ReleaseKeyMetaClass(class_ids[i]);
- }
- return REDISMODULE_OK;
-}