mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-22 08:08:53 -05:00
03d144a452
Replaces Redis => Redict API References: https://codeberg.org/redict/redict/issues/21 Signed-off-by: Drew DeVault <sir@cmpwn.com>
202 lines
8.1 KiB
C
202 lines
8.1 KiB
C
// SPDX-FileCopyrightText: 2024 Redict Contributors
|
|
// SPDX-FileCopyrightText: 2024 Salvatore Sanfilippo <antirez at gmail dot com>
|
|
//
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#include "redictmodule.h"
|
|
#include <strings.h>
|
|
int mutable_bool_val;
|
|
int immutable_bool_val;
|
|
long long longval;
|
|
long long memval;
|
|
RedictModuleString *strval = NULL;
|
|
int enumval;
|
|
int flagsval;
|
|
|
|
/* Series of get and set callbacks for each type of config, these rely on the privdata ptr
|
|
* to point to the config, and they register the configs as such. Note that one could also just
|
|
* use names if they wanted, and store anything in privdata. */
|
|
int getBoolConfigCommand(const char *name, void *privdata) {
|
|
REDICTMODULE_NOT_USED(name);
|
|
return (*(int *)privdata);
|
|
}
|
|
|
|
int setBoolConfigCommand(const char *name, int new, void *privdata, RedictModuleString **err) {
|
|
REDICTMODULE_NOT_USED(name);
|
|
REDICTMODULE_NOT_USED(err);
|
|
*(int *)privdata = new;
|
|
return REDICTMODULE_OK;
|
|
}
|
|
|
|
long long getNumericConfigCommand(const char *name, void *privdata) {
|
|
REDICTMODULE_NOT_USED(name);
|
|
return (*(long long *) privdata);
|
|
}
|
|
|
|
int setNumericConfigCommand(const char *name, long long new, void *privdata, RedictModuleString **err) {
|
|
REDICTMODULE_NOT_USED(name);
|
|
REDICTMODULE_NOT_USED(err);
|
|
*(long long *)privdata = new;
|
|
return REDICTMODULE_OK;
|
|
}
|
|
|
|
RedictModuleString *getStringConfigCommand(const char *name, void *privdata) {
|
|
REDICTMODULE_NOT_USED(name);
|
|
REDICTMODULE_NOT_USED(privdata);
|
|
return strval;
|
|
}
|
|
int setStringConfigCommand(const char *name, RedictModuleString *new, void *privdata, RedictModuleString **err) {
|
|
REDICTMODULE_NOT_USED(name);
|
|
REDICTMODULE_NOT_USED(err);
|
|
REDICTMODULE_NOT_USED(privdata);
|
|
size_t len;
|
|
if (!strcasecmp(RedictModule_StringPtrLen(new, &len), "rejectisfreed")) {
|
|
*err = RedictModule_CreateString(NULL, "Cannot set string to 'rejectisfreed'", 36);
|
|
return REDICTMODULE_ERR;
|
|
}
|
|
if (strval) RedictModule_FreeString(NULL, strval);
|
|
RedictModule_RetainString(NULL, new);
|
|
strval = new;
|
|
return REDICTMODULE_OK;
|
|
}
|
|
|
|
int getEnumConfigCommand(const char *name, void *privdata) {
|
|
REDICTMODULE_NOT_USED(name);
|
|
REDICTMODULE_NOT_USED(privdata);
|
|
return enumval;
|
|
}
|
|
|
|
int setEnumConfigCommand(const char *name, int val, void *privdata, RedictModuleString **err) {
|
|
REDICTMODULE_NOT_USED(name);
|
|
REDICTMODULE_NOT_USED(err);
|
|
REDICTMODULE_NOT_USED(privdata);
|
|
enumval = val;
|
|
return REDICTMODULE_OK;
|
|
}
|
|
|
|
int getFlagsConfigCommand(const char *name, void *privdata) {
|
|
REDICTMODULE_NOT_USED(name);
|
|
REDICTMODULE_NOT_USED(privdata);
|
|
return flagsval;
|
|
}
|
|
|
|
int setFlagsConfigCommand(const char *name, int val, void *privdata, RedictModuleString **err) {
|
|
REDICTMODULE_NOT_USED(name);
|
|
REDICTMODULE_NOT_USED(err);
|
|
REDICTMODULE_NOT_USED(privdata);
|
|
flagsval = val;
|
|
return REDICTMODULE_OK;
|
|
}
|
|
|
|
int boolApplyFunc(RedictModuleCtx *ctx, void *privdata, RedictModuleString **err) {
|
|
REDICTMODULE_NOT_USED(ctx);
|
|
REDICTMODULE_NOT_USED(privdata);
|
|
if (mutable_bool_val && immutable_bool_val) {
|
|
*err = RedictModule_CreateString(NULL, "Bool configs cannot both be yes.", 32);
|
|
return REDICTMODULE_ERR;
|
|
}
|
|
return REDICTMODULE_OK;
|
|
}
|
|
|
|
int longlongApplyFunc(RedictModuleCtx *ctx, void *privdata, RedictModuleString **err) {
|
|
REDICTMODULE_NOT_USED(ctx);
|
|
REDICTMODULE_NOT_USED(privdata);
|
|
if (longval == memval) {
|
|
*err = RedictModule_CreateString(NULL, "These configs cannot equal each other.", 38);
|
|
return REDICTMODULE_ERR;
|
|
}
|
|
return REDICTMODULE_OK;
|
|
}
|
|
|
|
int registerBlockCheck(RedictModuleCtx *ctx, RedictModuleString **argv, int argc) {
|
|
REDICTMODULE_NOT_USED(argv);
|
|
REDICTMODULE_NOT_USED(argc);
|
|
int response_ok = 0;
|
|
int result = RedictModule_RegisterBoolConfig(ctx, "mutable_bool", 1, REDICTMODULE_CONFIG_DEFAULT, getBoolConfigCommand, setBoolConfigCommand, boolApplyFunc, &mutable_bool_val);
|
|
response_ok |= (result == REDICTMODULE_OK);
|
|
|
|
result = RedictModule_RegisterStringConfig(ctx, "string", "secret password", REDICTMODULE_CONFIG_DEFAULT, getStringConfigCommand, setStringConfigCommand, NULL, NULL);
|
|
response_ok |= (result == REDICTMODULE_OK);
|
|
|
|
const char *enum_vals[] = {"none", "five", "one", "two", "four"};
|
|
const int int_vals[] = {0, 5, 1, 2, 4};
|
|
result = RedictModule_RegisterEnumConfig(ctx, "enum", 1, REDICTMODULE_CONFIG_DEFAULT, enum_vals, int_vals, 5, getEnumConfigCommand, setEnumConfigCommand, NULL, NULL);
|
|
response_ok |= (result == REDICTMODULE_OK);
|
|
|
|
result = RedictModule_RegisterNumericConfig(ctx, "numeric", -1, REDICTMODULE_CONFIG_DEFAULT, -5, 2000, getNumericConfigCommand, setNumericConfigCommand, longlongApplyFunc, &longval);
|
|
response_ok |= (result == REDICTMODULE_OK);
|
|
|
|
result = RedictModule_LoadConfigs(ctx);
|
|
response_ok |= (result == REDICTMODULE_OK);
|
|
|
|
/* This validates that it's not possible to register/load configs outside OnLoad,
|
|
* thus returns an error if they succeed. */
|
|
if (response_ok) {
|
|
RedictModule_ReplyWithError(ctx, "UNEXPECTEDOK");
|
|
} else {
|
|
RedictModule_ReplyWithSimpleString(ctx, "OK");
|
|
}
|
|
return REDICTMODULE_OK;
|
|
}
|
|
|
|
int RedictModule_OnLoad(RedictModuleCtx *ctx, RedictModuleString **argv, int argc) {
|
|
REDICTMODULE_NOT_USED(argv);
|
|
REDICTMODULE_NOT_USED(argc);
|
|
|
|
if (RedictModule_Init(ctx, "moduleconfigs", 1, REDICTMODULE_APIVER_1) == REDICTMODULE_ERR) return REDICTMODULE_ERR;
|
|
|
|
if (RedictModule_RegisterBoolConfig(ctx, "mutable_bool", 1, REDICTMODULE_CONFIG_DEFAULT, getBoolConfigCommand, setBoolConfigCommand, boolApplyFunc, &mutable_bool_val) == REDICTMODULE_ERR) {
|
|
return REDICTMODULE_ERR;
|
|
}
|
|
/* Immutable config here. */
|
|
if (RedictModule_RegisterBoolConfig(ctx, "immutable_bool", 0, REDICTMODULE_CONFIG_IMMUTABLE, getBoolConfigCommand, setBoolConfigCommand, boolApplyFunc, &immutable_bool_val) == REDICTMODULE_ERR) {
|
|
return REDICTMODULE_ERR;
|
|
}
|
|
if (RedictModule_RegisterStringConfig(ctx, "string", "secret password", REDICTMODULE_CONFIG_DEFAULT, getStringConfigCommand, setStringConfigCommand, NULL, NULL) == REDICTMODULE_ERR) {
|
|
return REDICTMODULE_ERR;
|
|
}
|
|
|
|
/* On the stack to make sure we're copying them. */
|
|
const char *enum_vals[] = {"none", "five", "one", "two", "four"};
|
|
const int int_vals[] = {0, 5, 1, 2, 4};
|
|
|
|
if (RedictModule_RegisterEnumConfig(ctx, "enum", 1, REDICTMODULE_CONFIG_DEFAULT, enum_vals, int_vals, 5, getEnumConfigCommand, setEnumConfigCommand, NULL, NULL) == REDICTMODULE_ERR) {
|
|
return REDICTMODULE_ERR;
|
|
}
|
|
if (RedictModule_RegisterEnumConfig(ctx, "flags", 3, REDICTMODULE_CONFIG_DEFAULT | REDICTMODULE_CONFIG_BITFLAGS, enum_vals, int_vals, 5, getFlagsConfigCommand, setFlagsConfigCommand, NULL, NULL) == REDICTMODULE_ERR) {
|
|
return REDICTMODULE_ERR;
|
|
}
|
|
/* Memory config here. */
|
|
if (RedictModule_RegisterNumericConfig(ctx, "memory_numeric", 1024, REDICTMODULE_CONFIG_DEFAULT | REDICTMODULE_CONFIG_MEMORY, 0, 3000000, getNumericConfigCommand, setNumericConfigCommand, longlongApplyFunc, &memval) == REDICTMODULE_ERR) {
|
|
return REDICTMODULE_ERR;
|
|
}
|
|
if (RedictModule_RegisterNumericConfig(ctx, "numeric", -1, REDICTMODULE_CONFIG_DEFAULT, -5, 2000, getNumericConfigCommand, setNumericConfigCommand, longlongApplyFunc, &longval) == REDICTMODULE_ERR) {
|
|
return REDICTMODULE_ERR;
|
|
}
|
|
size_t len;
|
|
if (argc && !strcasecmp(RedictModule_StringPtrLen(argv[0], &len), "noload")) {
|
|
return REDICTMODULE_OK;
|
|
} else if (RedictModule_LoadConfigs(ctx) == REDICTMODULE_ERR) {
|
|
if (strval) {
|
|
RedictModule_FreeString(ctx, strval);
|
|
strval = NULL;
|
|
}
|
|
return REDICTMODULE_ERR;
|
|
}
|
|
/* Creates a command which registers configs outside OnLoad() function. */
|
|
if (RedictModule_CreateCommand(ctx,"block.register.configs.outside.onload", registerBlockCheck, "write", 0, 0, 0) == REDICTMODULE_ERR)
|
|
return REDICTMODULE_ERR;
|
|
|
|
return REDICTMODULE_OK;
|
|
}
|
|
|
|
int RedictModule_OnUnload(RedictModuleCtx *ctx) {
|
|
REDICTMODULE_NOT_USED(ctx);
|
|
if (strval) {
|
|
RedictModule_FreeString(ctx, strval);
|
|
strval = NULL;
|
|
}
|
|
return REDICTMODULE_OK;
|
|
}
|