More improvements and fixes to generic config infra
- Adding is_valid_fn and update_fn, both return 1 for success and 0 for failure with an optional error message. - Bugfix in handling boundary check of unsigned numeric types (was boundaries as signed) - Adding more numeric types to generic mechanism: uint, ulonglong, long, time_t, off_t - More verbose error replies ("argument must be between" in out of range CONFIG SET (like config file parsing)
This commit is contained in:
parent
e0cc3c99d2
commit
28beb05aa3
305
src/config.c
305
src/config.c
@ -105,20 +105,32 @@ clientBufferLimitsConfig clientBufferLimitsDefaults[CLIENT_TYPE_OBUF_COUNT] = {
|
|||||||
{1024*1024*32, 1024*1024*8, 60} /* pubsub */
|
{1024*1024*32, 1024*1024*8, 60} /* pubsub */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Generic config infrastructure function pointers
|
||||||
|
* int is_valid_fn(val, err)
|
||||||
|
* Return 1 when val is valid, and 0 when invalid.
|
||||||
|
* Optionslly set err to a static error string.
|
||||||
|
* int update_fn(val, prev, err)
|
||||||
|
* This function is called only for CONFIG SET command (not at config file parsing)
|
||||||
|
* It is called after the actual config is applied,
|
||||||
|
* Return 1 for success, and 0 for failure.
|
||||||
|
* Optionslly set err to a static error string.
|
||||||
|
* On failure the config change will be reverted.
|
||||||
|
*/
|
||||||
|
|
||||||
/* Configuration values that require no special handling to set, get, load or
|
/* Configuration values that require no special handling to set, get, load or
|
||||||
* rewrite. */
|
* rewrite. */
|
||||||
typedef struct boolConfigData {
|
typedef struct boolConfigData {
|
||||||
int *config; /* The pointer to the server config this value is stored in */
|
int *config; /* The pointer to the server config this value is stored in */
|
||||||
const int default_value; /* The default value of the config on rewrite */
|
const int default_value; /* The default value of the config on rewrite */
|
||||||
int (*is_valid_fn)(int,char**); /* Optional function to check validity of new value */
|
int (*is_valid_fn)(int val, char **err); /* Optional function to check validity of new value (generic doc above) */
|
||||||
void (*update_fn)(int); /* Optional function to apply new value at runtime (only for CONFIG SET) */
|
int (*update_fn)(int val, int prev, char **err); /* Optional function to apply new value at runtime (generic doc above) */
|
||||||
} boolConfigData;
|
} boolConfigData;
|
||||||
|
|
||||||
typedef struct stringConfigData {
|
typedef struct stringConfigData {
|
||||||
char **config; /* Pointer to the server config this value is stored in. */
|
char **config; /* Pointer to the server config this value is stored in. */
|
||||||
const char *default_value; /* Default value of the config on rewrite. */
|
const char *default_value; /* Default value of the config on rewrite. */
|
||||||
int (*is_valid_fn)(char*,char**); /* Optional function to check validity of new value */
|
int (*is_valid_fn)(char* val, char **err); /* Optional function to check validity of new value (generic doc above) */
|
||||||
void (*update_fn)(char*); /* Optional function to apply new value at runtime (only for CONFIG SET) */
|
int (*update_fn)(char* val, char* prev, char **err); /* Optional function to apply new value at runtime (generic doc above) */
|
||||||
int convert_empty_to_null; /* Boolean indicating if empty strings should
|
int convert_empty_to_null; /* Boolean indicating if empty strings should
|
||||||
be stored as a NULL value. */
|
be stored as a NULL value. */
|
||||||
} stringConfigData;
|
} stringConfigData;
|
||||||
@ -127,31 +139,43 @@ typedef struct enumConfigData {
|
|||||||
int *config; /* The pointer to the server config this value is stored in */
|
int *config; /* The pointer to the server config this value is stored in */
|
||||||
configEnum *enum_value; /* The underlying enum type this data represents */
|
configEnum *enum_value; /* The underlying enum type this data represents */
|
||||||
const int default_value; /* The default value of the config on rewrite */
|
const int default_value; /* The default value of the config on rewrite */
|
||||||
int (*is_valid_fn)(int,char**); /* Optional function to check validity of new value */
|
int (*is_valid_fn)(int val, char **err); /* Optional function to check validity of new value (generic doc above) */
|
||||||
void (*update_fn)(int); /* Optional function to apply new value at runtime (only for CONFIG SET) */
|
int (*update_fn)(int val, int prev, char **err); /* Optional function to apply new value at runtime (generic doc above) */
|
||||||
} enumConfigData;
|
} enumConfigData;
|
||||||
|
|
||||||
typedef enum numericType {
|
typedef enum numericType {
|
||||||
NUMERIC_TYPE_INT,
|
NUMERIC_TYPE_INT,
|
||||||
|
NUMERIC_TYPE_UINT,
|
||||||
|
NUMERIC_TYPE_LONG,
|
||||||
|
NUMERIC_TYPE_ULONG,
|
||||||
NUMERIC_TYPE_LONG_LONG,
|
NUMERIC_TYPE_LONG_LONG,
|
||||||
NUMERIC_TYPE_UNSIGNED_LONG,
|
NUMERIC_TYPE_ULONG_LONG,
|
||||||
NUMERIC_TYPE_SIZE_T
|
NUMERIC_TYPE_SIZE_T,
|
||||||
|
NUMERIC_TYPE_SSIZE_T,
|
||||||
|
NUMERIC_TYPE_OFF_T,
|
||||||
|
NUMERIC_TYPE_TIME_T,
|
||||||
} numericType;
|
} numericType;
|
||||||
|
|
||||||
typedef struct numericConfigData {
|
typedef struct numericConfigData {
|
||||||
union {
|
union {
|
||||||
int *i;
|
int *i;
|
||||||
long long *ll;
|
unsigned int *ui;
|
||||||
|
long *l;
|
||||||
unsigned long *ul;
|
unsigned long *ul;
|
||||||
|
long long *ll;
|
||||||
|
unsigned long long *ull;
|
||||||
size_t *st;
|
size_t *st;
|
||||||
|
ssize_t *sst;
|
||||||
|
off_t *ot;
|
||||||
|
time_t *tt;
|
||||||
} config; /* The pointer to the numeric config this value is stored in */
|
} config; /* The pointer to the numeric config this value is stored in */
|
||||||
int is_memory; /* Indicates if this value can be loaded as a memory value */
|
int is_memory; /* Indicates if this value can be loaded as a memory value */
|
||||||
numericType numeric_type; /* An enum indicating the type of this value */
|
numericType numeric_type; /* An enum indicating the type of this value */
|
||||||
long long lower_bound; /* The lower bound of this numeric value */
|
long long lower_bound; /* The lower bound of this numeric value */
|
||||||
long long upper_bound; /* The upper bound of this numeric value */
|
long long upper_bound; /* The upper bound of this numeric value */
|
||||||
const long long default_value; /* The default value of the config on rewrite */
|
const long long default_value; /* The default value of the config on rewrite */
|
||||||
int (*is_valid_fn)(long long,char**); /* Optional function to check validity of new value */
|
int (*is_valid_fn)(long long val, char **err); /* Optional function to check validity of new value (generic doc above) */
|
||||||
void (*update_fn)(long long); /* Optional function to apply new value at runtime (only for CONFIG SET) */
|
int (*update_fn)(long long val, long long prev, char **err); /* Optional function to apply new value at runtime (generic doc above) */
|
||||||
} numericConfigData;
|
} numericConfigData;
|
||||||
|
|
||||||
typedef union typeData {
|
typedef union typeData {
|
||||||
@ -1910,9 +1934,12 @@ static int boolConfigSet(typeData data, sds value, char **err) {
|
|||||||
if (yn == -1) return 0;
|
if (yn == -1) return 0;
|
||||||
if (data.yesno.is_valid_fn && !data.yesno.is_valid_fn(yn, err))
|
if (data.yesno.is_valid_fn && !data.yesno.is_valid_fn(yn, err))
|
||||||
return 0;
|
return 0;
|
||||||
|
int prev = *(data.yesno.config);
|
||||||
*(data.yesno.config) = yn;
|
*(data.yesno.config) = yn;
|
||||||
if (data.yesno.update_fn)
|
if (data.yesno.update_fn && !data.yesno.update_fn(yn, prev, err)) {
|
||||||
data.yesno.update_fn(yn);
|
*(data.yesno.config) = prev;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1963,14 +1990,18 @@ static int stringConfigLoad(typeData data, sds *argv, int argc, char **err) {
|
|||||||
static int stringConfigSet(typeData data, sds value, char **err) {
|
static int stringConfigSet(typeData data, sds value, char **err) {
|
||||||
if (data.string.is_valid_fn && !data.string.is_valid_fn(value, err))
|
if (data.string.is_valid_fn && !data.string.is_valid_fn(value, err))
|
||||||
return 0;
|
return 0;
|
||||||
zfree(*data.string.config);
|
char *prev = *data.string.config;
|
||||||
if (data.string.convert_empty_to_null) {
|
if (data.string.convert_empty_to_null) {
|
||||||
*data.string.config = value[0] ? zstrdup(value) : NULL;
|
*data.string.config = value[0] ? zstrdup(value) : NULL;
|
||||||
} else {
|
} else {
|
||||||
*data.string.config = zstrdup(value);
|
*data.string.config = zstrdup(value);
|
||||||
}
|
}
|
||||||
if (data.string.update_fn)
|
if (data.string.update_fn && !data.string.update_fn(*data.string.config, prev, err)) {
|
||||||
data.string.update_fn(*data.string.config);
|
zfree(*data.string.config);
|
||||||
|
*data.string.config = prev;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
zfree(prev);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2039,9 +2070,12 @@ static int configEnumSet(typeData data, sds value, char **err) {
|
|||||||
if (enumval == INT_MIN) return 0;
|
if (enumval == INT_MIN) return 0;
|
||||||
if (data.enumd.is_valid_fn && !data.enumd.is_valid_fn(enumval, err))
|
if (data.enumd.is_valid_fn && !data.enumd.is_valid_fn(enumval, err))
|
||||||
return 0;
|
return 0;
|
||||||
|
int prev = *(data.enumd.config);
|
||||||
*(data.enumd.config) = enumval;
|
*(data.enumd.config) = enumval;
|
||||||
if (data.enumd.update_fn)
|
if (data.enumd.update_fn && !data.enumd.update_fn(enumval, prev, err)) {
|
||||||
data.enumd.update_fn(enumval);
|
*(data.enumd.config) = prev;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2065,17 +2099,59 @@ static void configEnumRewrite(typeData data, const char *name, struct rewriteCon
|
|||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Gets a 'long long val' and sets it into the union, using a macro to get
|
||||||
|
* compile time type check. */
|
||||||
|
#define SET_NUMERIC_TYPE(val) \
|
||||||
|
if (data.numeric.numeric_type == NUMERIC_TYPE_INT) { \
|
||||||
|
*(data.numeric.config.i) = (int) val; \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_UINT) { \
|
||||||
|
*(data.numeric.config.ui) = (unsigned int) val; \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG) { \
|
||||||
|
*(data.numeric.config.l) = (long) val; \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_ULONG) { \
|
||||||
|
*(data.numeric.config.ul) = (unsigned long) val; \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG_LONG) { \
|
||||||
|
*(data.numeric.config.ll) = (long long) val; \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_ULONG_LONG) { \
|
||||||
|
*(data.numeric.config.ull) = (unsigned long long) val; \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T) { \
|
||||||
|
*(data.numeric.config.st) = (size_t) val; \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_SSIZE_T) { \
|
||||||
|
*(data.numeric.config.sst) = (ssize_t) val; \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_OFF_T) { \
|
||||||
|
*(data.numeric.config.ot) = (off_t) val; \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_TIME_T) { \
|
||||||
|
*(data.numeric.config.tt) = (time_t) val; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gets a 'long long val' and sets it with the value from the union, using a
|
||||||
|
* macro to get compile time type check. */
|
||||||
|
#define GET_NUMERIC_TYPE(val) \
|
||||||
|
if (data.numeric.numeric_type == NUMERIC_TYPE_INT) { \
|
||||||
|
val = *(data.numeric.config.i); \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_UINT) { \
|
||||||
|
val = *(data.numeric.config.ui); \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG) { \
|
||||||
|
val = *(data.numeric.config.l); \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_ULONG) { \
|
||||||
|
val = *(data.numeric.config.ul); \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG_LONG) { \
|
||||||
|
val = *(data.numeric.config.ll); \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_ULONG_LONG) { \
|
||||||
|
val = *(data.numeric.config.ull); \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T) { \
|
||||||
|
val = *(data.numeric.config.st); \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_SSIZE_T) { \
|
||||||
|
val = *(data.numeric.config.sst); \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_OFF_T) { \
|
||||||
|
val = *(data.numeric.config.ot); \
|
||||||
|
} else if (data.numeric.numeric_type == NUMERIC_TYPE_TIME_T) { \
|
||||||
|
val = *(data.numeric.config.tt); \
|
||||||
|
}
|
||||||
|
|
||||||
/* Numeric configs */
|
/* Numeric configs */
|
||||||
static void numericConfigInit(typeData data) {
|
static void numericConfigInit(typeData data) {
|
||||||
if (data.numeric.numeric_type == NUMERIC_TYPE_INT) {
|
SET_NUMERIC_TYPE(data.numeric.default_value)
|
||||||
*(data.numeric.config.i) = (int) data.numeric.default_value;
|
|
||||||
} else if (data.numeric.numeric_type == NUMERIC_TYPE_UNSIGNED_LONG) {
|
|
||||||
*(data.numeric.config.ul) = (unsigned long) data.numeric.default_value;
|
|
||||||
} else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG_LONG) {
|
|
||||||
*(data.numeric.config.ll) = (long long) data.numeric.default_value;
|
|
||||||
} else if (data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T) {
|
|
||||||
*(data.numeric.config.st) = (size_t) data.numeric.default_value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int numericConfigLoad(typeData data, sds *argv, int argc, char **err) {
|
static int numericConfigLoad(typeData data, sds *argv, int argc, char **err) {
|
||||||
@ -2100,34 +2176,44 @@ static int numericConfigLoad(typeData data, sds *argv, int argc, char **err) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ll > data.numeric.upper_bound ||
|
if (data.numeric.numeric_type == NUMERIC_TYPE_ULONG_LONG ||
|
||||||
ll < data.numeric.lower_bound) {
|
data.numeric.numeric_type == NUMERIC_TYPE_UINT ||
|
||||||
snprintf(loadbuf, LOADBUF_SIZE,
|
data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T) {
|
||||||
"argument must be between %lld and %lld inclusive",
|
/* Boundary check for unsigned types */
|
||||||
data.numeric.lower_bound,
|
unsigned long long ull = ll;
|
||||||
data.numeric.upper_bound);
|
unsigned long long upper_bound = data.numeric.upper_bound;
|
||||||
*err = loadbuf;
|
unsigned long long lower_bound = data.numeric.lower_bound;
|
||||||
return 0;
|
if (ull > upper_bound || ull < lower_bound) {
|
||||||
|
snprintf(loadbuf, LOADBUF_SIZE,
|
||||||
|
"argument must be between %llu and %llu inclusive",
|
||||||
|
lower_bound,
|
||||||
|
upper_bound);
|
||||||
|
*err = loadbuf;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Boundary check for signed types */
|
||||||
|
if (ll > data.numeric.upper_bound ||
|
||||||
|
ll < data.numeric.lower_bound) {
|
||||||
|
snprintf(loadbuf, LOADBUF_SIZE,
|
||||||
|
"argument must be between %lld and %lld inclusive",
|
||||||
|
data.numeric.lower_bound,
|
||||||
|
data.numeric.upper_bound);
|
||||||
|
*err = loadbuf;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.numeric.is_valid_fn && !data.numeric.is_valid_fn(ll, err))
|
if (data.numeric.is_valid_fn && !data.numeric.is_valid_fn(ll, err))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (data.numeric.numeric_type == NUMERIC_TYPE_INT) {
|
SET_NUMERIC_TYPE(ll)
|
||||||
*(data.numeric.config.i) = (int) ll;
|
|
||||||
} else if (data.numeric.numeric_type == NUMERIC_TYPE_UNSIGNED_LONG) {
|
|
||||||
*(data.numeric.config.ul) = (unsigned long) ll;
|
|
||||||
} else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG_LONG) {
|
|
||||||
*(data.numeric.config.ll) = ll;
|
|
||||||
} else if (data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T) {
|
|
||||||
*(data.numeric.config.st) = (size_t) ll;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int numericConfigSet(typeData data, sds value, char **err) {
|
static int numericConfigSet(typeData data, sds value, char **err) {
|
||||||
long long ll;
|
long long ll, prev = 0;
|
||||||
if (data.numeric.is_memory) {
|
if (data.numeric.is_memory) {
|
||||||
int memerr;
|
int memerr;
|
||||||
ll = memtoll(value, &memerr);
|
ll = memtoll(value, &memerr);
|
||||||
@ -2136,26 +2222,44 @@ static int numericConfigSet(typeData data, sds value, char **err) {
|
|||||||
if (!string2ll(value, sdslen(value),&ll)) return 0;
|
if (!string2ll(value, sdslen(value),&ll)) return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ll > data.numeric.upper_bound ||
|
if (data.numeric.numeric_type == NUMERIC_TYPE_ULONG_LONG ||
|
||||||
ll < data.numeric.lower_bound) {
|
data.numeric.numeric_type == NUMERIC_TYPE_UINT ||
|
||||||
return 0;
|
data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T) {
|
||||||
|
/* Boundary check for unsigned types */
|
||||||
|
unsigned long long ull = ll;
|
||||||
|
unsigned long long upper_bound = data.numeric.upper_bound;
|
||||||
|
unsigned long long lower_bound = data.numeric.lower_bound;
|
||||||
|
if (ull > upper_bound || ull < lower_bound) {
|
||||||
|
snprintf(loadbuf, LOADBUF_SIZE,
|
||||||
|
"argument must be between %llu and %llu inclusive",
|
||||||
|
lower_bound,
|
||||||
|
upper_bound);
|
||||||
|
*err = loadbuf;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Boundary check for signed types */
|
||||||
|
if (ll > data.numeric.upper_bound ||
|
||||||
|
ll < data.numeric.lower_bound) {
|
||||||
|
snprintf(loadbuf, LOADBUF_SIZE,
|
||||||
|
"argument must be between %lld and %lld inclusive",
|
||||||
|
data.numeric.lower_bound,
|
||||||
|
data.numeric.upper_bound);
|
||||||
|
*err = loadbuf;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.numeric.is_valid_fn && !data.numeric.is_valid_fn(ll, err))
|
if (data.numeric.is_valid_fn && !data.numeric.is_valid_fn(ll, err))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (data.numeric.numeric_type == NUMERIC_TYPE_INT) {
|
GET_NUMERIC_TYPE(prev)
|
||||||
*(data.numeric.config.i) = (int) ll;
|
SET_NUMERIC_TYPE(ll)
|
||||||
} else if (data.numeric.numeric_type == NUMERIC_TYPE_UNSIGNED_LONG) {
|
|
||||||
*(data.numeric.config.ul) = (unsigned long) ll;
|
|
||||||
} else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG_LONG) {
|
|
||||||
*(data.numeric.config.ll) = ll;
|
|
||||||
} else if (data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T) {
|
|
||||||
*(data.numeric.config.st) = (size_t) ll;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.numeric.update_fn)
|
if (data.numeric.update_fn && !data.numeric.update_fn(ll, prev, err)) {
|
||||||
data.numeric.update_fn(ll);
|
SET_NUMERIC_TYPE(prev)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2163,15 +2267,7 @@ static void numericConfigGet(client *c, typeData data) {
|
|||||||
char buf[128];
|
char buf[128];
|
||||||
long long value = 0;
|
long long value = 0;
|
||||||
|
|
||||||
if (data.numeric.numeric_type == NUMERIC_TYPE_INT) {
|
GET_NUMERIC_TYPE(value)
|
||||||
value = *(data.numeric.config.i);
|
|
||||||
} else if (data.numeric.numeric_type == NUMERIC_TYPE_UNSIGNED_LONG) {
|
|
||||||
value = *(data.numeric.config.ul);
|
|
||||||
} else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG_LONG) {
|
|
||||||
value = *(data.numeric.config.ll);
|
|
||||||
} else if (data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T) {
|
|
||||||
value = *(data.numeric.config.st);
|
|
||||||
}
|
|
||||||
|
|
||||||
ll2string(buf, sizeof(buf), value);
|
ll2string(buf, sizeof(buf), value);
|
||||||
addReplyBulkCString(c, buf);
|
addReplyBulkCString(c, buf);
|
||||||
@ -2179,15 +2275,8 @@ static void numericConfigGet(client *c, typeData data) {
|
|||||||
|
|
||||||
static void numericConfigRewrite(typeData data, const char *name, struct rewriteConfigState *state) {
|
static void numericConfigRewrite(typeData data, const char *name, struct rewriteConfigState *state) {
|
||||||
long long value = 0;
|
long long value = 0;
|
||||||
if (data.numeric.numeric_type == NUMERIC_TYPE_INT) {
|
|
||||||
value = *(data.numeric.config.i);
|
GET_NUMERIC_TYPE(value)
|
||||||
} else if (data.numeric.numeric_type == NUMERIC_TYPE_UNSIGNED_LONG) {
|
|
||||||
value = *(data.numeric.config.ul);
|
|
||||||
} else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG_LONG) {
|
|
||||||
value = *(data.numeric.config.ll);
|
|
||||||
} else if (data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T) {
|
|
||||||
value = *(data.numeric.config.st);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.numeric.is_memory) {
|
if (data.numeric.is_memory) {
|
||||||
rewriteConfigBytesOption(state, name, value, data.numeric.default_value);
|
rewriteConfigBytesOption(state, name, value, data.numeric.default_value);
|
||||||
@ -2217,9 +2306,23 @@ static void numericConfigRewrite(typeData data, const char *name, struct rewrite
|
|||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define createUnsignedLongConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
#define createUIntConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
||||||
embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
||||||
.numeric_type = NUMERIC_TYPE_UNSIGNED_LONG, \
|
.numeric_type = NUMERIC_TYPE_UINT, \
|
||||||
|
.config.ui = &(config_addr) \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define createLongConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
||||||
|
embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
||||||
|
.numeric_type = NUMERIC_TYPE_LONG, \
|
||||||
|
.config.l = &(config_addr) \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define createULongConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
||||||
|
embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
||||||
|
.numeric_type = NUMERIC_TYPE_ULONG, \
|
||||||
.config.ul = &(config_addr) \
|
.config.ul = &(config_addr) \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
@ -2231,6 +2334,13 @@ static void numericConfigRewrite(typeData data, const char *name, struct rewrite
|
|||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define createULongLongConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
||||||
|
embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
||||||
|
.numeric_type = NUMERIC_TYPE_ULONG_LONG, \
|
||||||
|
.config.ull = &(config_addr) \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
#define createSizeTConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
#define createSizeTConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
||||||
embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
||||||
.numeric_type = NUMERIC_TYPE_SIZE_T, \
|
.numeric_type = NUMERIC_TYPE_SIZE_T, \
|
||||||
@ -2238,7 +2348,28 @@ static void numericConfigRewrite(typeData data, const char *name, struct rewrite
|
|||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_active_defrag_valid(int val, char **err) {
|
#define createSSizeTConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
||||||
|
embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
||||||
|
.numeric_type = NUMERIC_TYPE_SSIZE_T, \
|
||||||
|
.config.sst = &(config_addr) \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define createTimeTConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
||||||
|
embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
||||||
|
.numeric_type = NUMERIC_TYPE_TIME_T, \
|
||||||
|
.config.tt = &(config_addr) \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define createOffTConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
||||||
|
embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update) \
|
||||||
|
.numeric_type = NUMERIC_TYPE_OFF_T, \
|
||||||
|
.config.ot = &(config_addr) \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
static int isValidActiveDefrag(int val, char **err) {
|
||||||
#ifndef HAVE_DEFRAG
|
#ifndef HAVE_DEFRAG
|
||||||
if (val) {
|
if (val) {
|
||||||
*err = "Active defragmentation cannot be enabled: it "
|
*err = "Active defragmentation cannot be enabled: it "
|
||||||
@ -2254,6 +2385,12 @@ int is_active_defrag_valid(int val, char **err) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int updateJemallocBgThread(int val, int prev, char **err) {
|
||||||
|
UNUSED(prev);
|
||||||
|
UNUSED(err);
|
||||||
|
set_jemalloc_bg_thread(val);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
standardConfig configs[] = {
|
standardConfig configs[] = {
|
||||||
/* Bool configs */
|
/* Bool configs */
|
||||||
@ -2284,8 +2421,8 @@ standardConfig configs[] = {
|
|||||||
createBoolConfig("replica-serve-stale-data", "slave-serve-stale-data", MODIFIABLE_CONFIG, server.repl_serve_stale_data, CONFIG_DEFAULT_SLAVE_SERVE_STALE_DATA ,NULL, NULL),
|
createBoolConfig("replica-serve-stale-data", "slave-serve-stale-data", MODIFIABLE_CONFIG, server.repl_serve_stale_data, CONFIG_DEFAULT_SLAVE_SERVE_STALE_DATA ,NULL, NULL),
|
||||||
createBoolConfig("replica-read-only", "slave-read-only", MODIFIABLE_CONFIG, server.repl_slave_ro, CONFIG_DEFAULT_SLAVE_READ_ONLY ,NULL, NULL),
|
createBoolConfig("replica-read-only", "slave-read-only", MODIFIABLE_CONFIG, server.repl_slave_ro, CONFIG_DEFAULT_SLAVE_READ_ONLY ,NULL, NULL),
|
||||||
createBoolConfig("replica-ignore-maxmemory", "slave-ignore-maxmemory", MODIFIABLE_CONFIG, server.repl_slave_ignore_maxmemory, CONFIG_DEFAULT_SLAVE_IGNORE_MAXMEMORY ,NULL, NULL),
|
createBoolConfig("replica-ignore-maxmemory", "slave-ignore-maxmemory", MODIFIABLE_CONFIG, server.repl_slave_ignore_maxmemory, CONFIG_DEFAULT_SLAVE_IGNORE_MAXMEMORY ,NULL, NULL),
|
||||||
createBoolConfig("jemalloc-bg-thread", NULL, MODIFIABLE_CONFIG, server.jemalloc_bg_thread, 1, NULL, set_jemalloc_bg_thread),
|
createBoolConfig("jemalloc-bg-thread", NULL, MODIFIABLE_CONFIG, server.jemalloc_bg_thread, 1, NULL, updateJemallocBgThread),
|
||||||
createBoolConfig("activedefrag",NULL, MODIFIABLE_CONFIG, server.active_defrag_enabled, 0, is_active_defrag_valid, NULL),
|
createBoolConfig("activedefrag", NULL, MODIFIABLE_CONFIG, server.active_defrag_enabled, 0, isValidActiveDefrag, NULL),
|
||||||
|
|
||||||
/* String Configs */
|
/* String Configs */
|
||||||
createStringConfig("aclfile", NULL, IMMUTABLE_CONFIG, ALLOW_EMPTY_STRING, server.acl_filename, CONFIG_DEFAULT_ACL_FILENAME ,NULL, NULL),
|
createStringConfig("aclfile", NULL, IMMUTABLE_CONFIG, ALLOW_EMPTY_STRING, server.acl_filename, CONFIG_DEFAULT_ACL_FILENAME ,NULL, NULL),
|
||||||
@ -2336,8 +2473,8 @@ standardConfig configs[] = {
|
|||||||
createIntConfig("active-expire-effort", NULL, MODIFIABLE_CONFIG, 1, 10, server.active_expire_effort, CONFIG_DEFAULT_ACTIVE_EXPIRE_EFFORT, INTEGER_CONFIG ,NULL, NULL),
|
createIntConfig("active-expire-effort", NULL, MODIFIABLE_CONFIG, 1, 10, server.active_expire_effort, CONFIG_DEFAULT_ACTIVE_EXPIRE_EFFORT, INTEGER_CONFIG ,NULL, NULL),
|
||||||
|
|
||||||
/* Unsigned Long configs */
|
/* Unsigned Long configs */
|
||||||
createUnsignedLongConfig("active-defrag-max-scan-fields", NULL, MODIFIABLE_CONFIG, 1, LONG_MAX, server.active_defrag_max_scan_fields, CONFIG_DEFAULT_DEFRAG_MAX_SCAN_FIELDS, INTEGER_CONFIG ,NULL, NULL),
|
createULongConfig("active-defrag-max-scan-fields", NULL, MODIFIABLE_CONFIG, 1, LONG_MAX, server.active_defrag_max_scan_fields, CONFIG_DEFAULT_DEFRAG_MAX_SCAN_FIELDS, INTEGER_CONFIG ,NULL, NULL),
|
||||||
createUnsignedLongConfig("slowlog-max-len", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.slowlog_max_len, CONFIG_DEFAULT_SLOWLOG_MAX_LEN, INTEGER_CONFIG ,NULL, NULL),
|
createULongConfig("slowlog-max-len", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.slowlog_max_len, CONFIG_DEFAULT_SLOWLOG_MAX_LEN, INTEGER_CONFIG ,NULL, NULL),
|
||||||
|
|
||||||
/* Long Long configs */
|
/* Long Long configs */
|
||||||
createLongLongConfig("lua-time-limit", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.lua_time_limit, LUA_SCRIPT_TIME_LIMIT, INTEGER_CONFIG ,NULL, NULL),
|
createLongLongConfig("lua-time-limit", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.lua_time_limit, LUA_SCRIPT_TIME_LIMIT, INTEGER_CONFIG ,NULL, NULL),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user