mirror of
https://github.com/fluencelabs/redis
synced 2025-04-25 18:42:13 +00:00
Add RM_ServerInfoGetFieldUnsigned
rename RM_ServerInfoGetFieldNumerical RM_ServerInfoGetFieldSigned move string2ull to util.c fix leak in RM_GetServerInfo when duplicate info fields exist
This commit is contained in:
parent
deebed23e1
commit
0423309768
30
src/module.c
30
src/module.c
@ -5497,7 +5497,8 @@ RedisModuleServerInfoData *RM_GetServerInfo(RedisModuleCtx *ctx, const char *sec
|
|||||||
unsigned char *key = (unsigned char*)line;
|
unsigned char *key = (unsigned char*)line;
|
||||||
size_t keylen = (intptr_t)sep-(intptr_t)line;
|
size_t keylen = (intptr_t)sep-(intptr_t)line;
|
||||||
sds val = sdsnewlen(sep+1,sdslen(line)-((intptr_t)sep-(intptr_t)line)-1);
|
sds val = sdsnewlen(sep+1,sdslen(line)-((intptr_t)sep-(intptr_t)line)-1);
|
||||||
raxTryInsert(d->rax,key,keylen,val,NULL);
|
if (!raxTryInsert(d->rax,key,keylen,val,NULL))
|
||||||
|
sdsfree(val);
|
||||||
}
|
}
|
||||||
sdsfree(info);
|
sdsfree(info);
|
||||||
sdsfreesplitres(lines,totlines);
|
sdsfreesplitres(lines,totlines);
|
||||||
@ -5542,9 +5543,9 @@ const char *RM_ServerInfoGetFieldC(RedisModuleServerInfoData *data, const char*
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get the value of a field from data collected with RM_GetServerInfo(). If the
|
/* Get the value of a field from data collected with RM_GetServerInfo(). If the
|
||||||
* field is not found, or is not numerical, return value will be 0, and the
|
* field is not found, or is not numerical or out of range, return value will be
|
||||||
* optional out_err argument will be set to REDISMODULE_ERR. */
|
* 0, and the optional out_err argument will be set to REDISMODULE_ERR. */
|
||||||
long long RM_ServerInfoGetFieldNumerical(RedisModuleServerInfoData *data, const char* field, int *out_err) {
|
long long RM_ServerInfoGetFieldSigned(RedisModuleServerInfoData *data, const char* field, int *out_err) {
|
||||||
long long ll;
|
long long ll;
|
||||||
sds val = raxFind(data->rax, (unsigned char *)field, strlen(field));
|
sds val = raxFind(data->rax, (unsigned char *)field, strlen(field));
|
||||||
if (val == raxNotFound) {
|
if (val == raxNotFound) {
|
||||||
@ -5559,6 +5560,24 @@ long long RM_ServerInfoGetFieldNumerical(RedisModuleServerInfoData *data, const
|
|||||||
return ll;
|
return ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the value of a field from data collected with RM_GetServerInfo(). If the
|
||||||
|
* field is not found, or is not numerical or out of range, return value will be
|
||||||
|
* 0, and the optional out_err argument will be set to REDISMODULE_ERR. */
|
||||||
|
unsigned long long RM_ServerInfoGetFieldUnsigned(RedisModuleServerInfoData *data, const char* field, int *out_err) {
|
||||||
|
unsigned long long ll;
|
||||||
|
sds val = raxFind(data->rax, (unsigned char *)field, strlen(field));
|
||||||
|
if (val == raxNotFound) {
|
||||||
|
if (out_err) *out_err = REDISMODULE_ERR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!string2ull(val,&ll)) {
|
||||||
|
if (out_err) *out_err = REDISMODULE_ERR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (out_err) *out_err = REDISMODULE_OK;
|
||||||
|
return ll;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the value of a field from data collected with RM_GetServerInfo(). If the
|
/* Get the value of a field from data collected with RM_GetServerInfo(). If the
|
||||||
* field is not found, or is not a double, return value will be 0, and the
|
* field is not found, or is not a double, return value will be 0, and the
|
||||||
* optional out_err argument will be set to REDISMODULE_ERR. */
|
* optional out_err argument will be set to REDISMODULE_ERR. */
|
||||||
@ -6868,7 +6887,8 @@ void moduleRegisterCoreAPI(void) {
|
|||||||
REGISTER_API(FreeServerInfo);
|
REGISTER_API(FreeServerInfo);
|
||||||
REGISTER_API(ServerInfoGetField);
|
REGISTER_API(ServerInfoGetField);
|
||||||
REGISTER_API(ServerInfoGetFieldC);
|
REGISTER_API(ServerInfoGetFieldC);
|
||||||
REGISTER_API(ServerInfoGetFieldNumerical);
|
REGISTER_API(ServerInfoGetFieldSigned);
|
||||||
|
REGISTER_API(ServerInfoGetFieldUnsigned);
|
||||||
REGISTER_API(ServerInfoGetFieldDouble);
|
REGISTER_API(ServerInfoGetFieldDouble);
|
||||||
REGISTER_API(GetClientInfoById);
|
REGISTER_API(GetClientInfoById);
|
||||||
REGISTER_API(SubscribeToServerEvent);
|
REGISTER_API(SubscribeToServerEvent);
|
||||||
|
@ -507,7 +507,8 @@ RedisModuleServerInfoData *REDISMODULE_API_FUNC(RedisModule_GetServerInfo)(Redis
|
|||||||
void REDISMODULE_API_FUNC(RedisModule_FreeServerInfo)(RedisModuleCtx *ctx, RedisModuleServerInfoData *data);
|
void REDISMODULE_API_FUNC(RedisModule_FreeServerInfo)(RedisModuleCtx *ctx, RedisModuleServerInfoData *data);
|
||||||
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_ServerInfoGetField)(RedisModuleCtx *ctx, RedisModuleServerInfoData *data, const char* field);
|
RedisModuleString *REDISMODULE_API_FUNC(RedisModule_ServerInfoGetField)(RedisModuleCtx *ctx, RedisModuleServerInfoData *data, const char* field);
|
||||||
const char *REDISMODULE_API_FUNC(RedisModule_ServerInfoGetFieldC)(RedisModuleServerInfoData *data, const char* field);
|
const char *REDISMODULE_API_FUNC(RedisModule_ServerInfoGetFieldC)(RedisModuleServerInfoData *data, const char* field);
|
||||||
long long REDISMODULE_API_FUNC(RedisModule_ServerInfoGetFieldNumerical)(RedisModuleServerInfoData *data, const char* field, int *out_err);
|
long long REDISMODULE_API_FUNC(RedisModule_ServerInfoGetFieldSigned)(RedisModuleServerInfoData *data, const char* field, int *out_err);
|
||||||
|
unsigned long long REDISMODULE_API_FUNC(RedisModule_ServerInfoGetFieldUnsigned)(RedisModuleServerInfoData *data, const char* field, int *out_err);
|
||||||
double REDISMODULE_API_FUNC(RedisModule_ServerInfoGetFieldDouble)(RedisModuleServerInfoData *data, const char* field, int *out_err);
|
double REDISMODULE_API_FUNC(RedisModule_ServerInfoGetFieldDouble)(RedisModuleServerInfoData *data, const char* field, int *out_err);
|
||||||
int REDISMODULE_API_FUNC(RedisModule_SubscribeToServerEvent)(RedisModuleCtx *ctx, RedisModuleEvent event, RedisModuleEventCallback callback);
|
int REDISMODULE_API_FUNC(RedisModule_SubscribeToServerEvent)(RedisModuleCtx *ctx, RedisModuleEvent event, RedisModuleEventCallback callback);
|
||||||
RedisModuleBlockedClient *REDISMODULE_API_FUNC(RedisModule_BlockClientOnKeys)(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*), long long timeout_ms, RedisModuleString **keys, int numkeys, void *privdata);
|
RedisModuleBlockedClient *REDISMODULE_API_FUNC(RedisModule_BlockClientOnKeys)(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*), long long timeout_ms, RedisModuleString **keys, int numkeys, void *privdata);
|
||||||
@ -715,7 +716,8 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
|
|||||||
REDISMODULE_GET_API(FreeServerInfo);
|
REDISMODULE_GET_API(FreeServerInfo);
|
||||||
REDISMODULE_GET_API(ServerInfoGetField);
|
REDISMODULE_GET_API(ServerInfoGetField);
|
||||||
REDISMODULE_GET_API(ServerInfoGetFieldC);
|
REDISMODULE_GET_API(ServerInfoGetFieldC);
|
||||||
REDISMODULE_GET_API(ServerInfoGetFieldNumerical);
|
REDISMODULE_GET_API(ServerInfoGetFieldSigned);
|
||||||
|
REDISMODULE_GET_API(ServerInfoGetFieldUnsigned);
|
||||||
REDISMODULE_GET_API(ServerInfoGetFieldDouble);
|
REDISMODULE_GET_API(ServerInfoGetFieldDouble);
|
||||||
REDISMODULE_GET_API(GetClientInfoById);
|
REDISMODULE_GET_API(GetClientInfoById);
|
||||||
REDISMODULE_GET_API(SubscribeToServerEvent);
|
REDISMODULE_GET_API(SubscribeToServerEvent);
|
||||||
|
@ -1070,26 +1070,6 @@ robj *streamTypeLookupWriteOrCreate(client *c, robj *key) {
|
|||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper function to convert a string to an unsigned long long value.
|
|
||||||
* The function attempts to use the faster string2ll() function inside
|
|
||||||
* Redis: if it fails, strtoull() is used instead. The function returns
|
|
||||||
* 1 if the conversion happened successfully or 0 if the number is
|
|
||||||
* invalid or out of range. */
|
|
||||||
int string2ull(const char *s, unsigned long long *value) {
|
|
||||||
long long ll;
|
|
||||||
if (string2ll(s,strlen(s),&ll)) {
|
|
||||||
if (ll < 0) return 0; /* Negative values are out of range. */
|
|
||||||
*value = ll;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
errno = 0;
|
|
||||||
char *endptr = NULL;
|
|
||||||
*value = strtoull(s,&endptr,10);
|
|
||||||
if (errno == EINVAL || errno == ERANGE || !(*s != '\0' && *endptr == '\0'))
|
|
||||||
return 0; /* strtoull() failed. */
|
|
||||||
return 1; /* Conversion done! */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse a stream ID in the format given by clients to Redis, that is
|
/* Parse a stream ID in the format given by clients to Redis, that is
|
||||||
* <ms>-<seq>, and converts it into a streamID structure. If
|
* <ms>-<seq>, and converts it into a streamID structure. If
|
||||||
* the specified ID is invalid C_ERR is returned and an error is reported
|
* the specified ID is invalid C_ERR is returned and an error is reported
|
||||||
|
20
src/util.c
20
src/util.c
@ -423,6 +423,26 @@ int string2ll(const char *s, size_t slen, long long *value) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper function to convert a string to an unsigned long long value.
|
||||||
|
* The function attempts to use the faster string2ll() function inside
|
||||||
|
* Redis: if it fails, strtoull() is used instead. The function returns
|
||||||
|
* 1 if the conversion happened successfully or 0 if the number is
|
||||||
|
* invalid or out of range. */
|
||||||
|
int string2ull(const char *s, unsigned long long *value) {
|
||||||
|
long long ll;
|
||||||
|
if (string2ll(s,strlen(s),&ll)) {
|
||||||
|
if (ll < 0) return 0; /* Negative values are out of range. */
|
||||||
|
*value = ll;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
errno = 0;
|
||||||
|
char *endptr = NULL;
|
||||||
|
*value = strtoull(s,&endptr,10);
|
||||||
|
if (errno == EINVAL || errno == ERANGE || !(*s != '\0' && *endptr == '\0'))
|
||||||
|
return 0; /* strtoull() failed. */
|
||||||
|
return 1; /* Conversion done! */
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert a string into a long. Returns 1 if the string could be parsed into a
|
/* Convert a string into a long. Returns 1 if the string could be parsed into a
|
||||||
* (non-overflowing) long, 0 otherwise. The value will be set to the parsed
|
* (non-overflowing) long, 0 otherwise. The value will be set to the parsed
|
||||||
* value when appropriate. */
|
* value when appropriate. */
|
||||||
|
@ -46,6 +46,7 @@ uint32_t digits10(uint64_t v);
|
|||||||
uint32_t sdigits10(int64_t v);
|
uint32_t sdigits10(int64_t v);
|
||||||
int ll2string(char *s, size_t len, long long value);
|
int ll2string(char *s, size_t len, long long value);
|
||||||
int string2ll(const char *s, size_t slen, long long *value);
|
int string2ll(const char *s, size_t slen, long long *value);
|
||||||
|
int string2ull(const char *s, unsigned long long *value);
|
||||||
int string2l(const char *s, size_t slen, long *value);
|
int string2l(const char *s, size_t slen, long *value);
|
||||||
int string2ld(const char *s, size_t slen, long double *dp);
|
int string2ld(const char *s, size_t slen, long double *dp);
|
||||||
int string2d(const char *s, size_t slen, double *dp);
|
int string2d(const char *s, size_t slen, double *dp);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
void InfoFunc(RedisModuleInfoCtx *ctx, int for_crash_report) {
|
void InfoFunc(RedisModuleInfoCtx *ctx, int for_crash_report) {
|
||||||
RedisModule_InfoAddSection(ctx, "");
|
RedisModule_InfoAddSection(ctx, "");
|
||||||
RedisModule_InfoAddFieldLongLong(ctx, "global", -2);
|
RedisModule_InfoAddFieldLongLong(ctx, "global", -2);
|
||||||
|
RedisModule_InfoAddFieldULongLong(ctx, "uglobal", (unsigned long long)-2);
|
||||||
|
|
||||||
RedisModule_InfoAddSection(ctx, "Spanish");
|
RedisModule_InfoAddSection(ctx, "Spanish");
|
||||||
RedisModule_InfoAddFieldCString(ctx, "uno", "one");
|
RedisModule_InfoAddFieldCString(ctx, "uno", "one");
|
||||||
@ -41,7 +42,11 @@ int info_get(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, char field
|
|||||||
field = RedisModule_StringPtrLen(argv[2], NULL);
|
field = RedisModule_StringPtrLen(argv[2], NULL);
|
||||||
RedisModuleServerInfoData *info = RedisModule_GetServerInfo(ctx, section);
|
RedisModuleServerInfoData *info = RedisModule_GetServerInfo(ctx, section);
|
||||||
if (field_type=='i') {
|
if (field_type=='i') {
|
||||||
long long ll = RedisModule_ServerInfoGetFieldNumerical(info, field, &err);
|
long long ll = RedisModule_ServerInfoGetFieldSigned(info, field, &err);
|
||||||
|
if (err==REDISMODULE_OK)
|
||||||
|
RedisModule_ReplyWithLongLong(ctx, ll);
|
||||||
|
} else if (field_type=='u') {
|
||||||
|
unsigned long long ll = (unsigned long long)RedisModule_ServerInfoGetFieldUnsigned(info, field, &err);
|
||||||
if (err==REDISMODULE_OK)
|
if (err==REDISMODULE_OK)
|
||||||
RedisModule_ReplyWithLongLong(ctx, ll);
|
RedisModule_ReplyWithLongLong(ctx, ll);
|
||||||
} else if (field_type=='d') {
|
} else if (field_type=='d') {
|
||||||
@ -78,6 +83,10 @@ int info_geti(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
|
|||||||
return info_get(ctx, argv, argc, 'i');
|
return info_get(ctx, argv, argc, 'i');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int info_getu(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
|
||||||
|
return info_get(ctx, argv, argc, 'u');
|
||||||
|
}
|
||||||
|
|
||||||
int info_getd(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
|
int info_getd(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
|
||||||
return info_get(ctx, argv, argc, 'd');
|
return info_get(ctx, argv, argc, 'd');
|
||||||
}
|
}
|
||||||
@ -96,6 +105,8 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
|||||||
return REDISMODULE_ERR;
|
return REDISMODULE_ERR;
|
||||||
if (RedisModule_CreateCommand(ctx,"info.geti", info_geti,"",0,0,0) == REDISMODULE_ERR)
|
if (RedisModule_CreateCommand(ctx,"info.geti", info_geti,"",0,0,0) == REDISMODULE_ERR)
|
||||||
return REDISMODULE_ERR;
|
return REDISMODULE_ERR;
|
||||||
|
if (RedisModule_CreateCommand(ctx,"info.getu", info_getu,"",0,0,0) == REDISMODULE_ERR)
|
||||||
|
return REDISMODULE_ERR;
|
||||||
if (RedisModule_CreateCommand(ctx,"info.getd", info_getd,"",0,0,0) == REDISMODULE_ERR)
|
if (RedisModule_CreateCommand(ctx,"info.getd", info_getd,"",0,0,0) == REDISMODULE_ERR)
|
||||||
return REDISMODULE_ERR;
|
return REDISMODULE_ERR;
|
||||||
|
|
||||||
|
@ -17,6 +17,10 @@ start_server {tags {"modules"}} {
|
|||||||
assert_equal [r info.geti stats expired_keys] 0
|
assert_equal [r info.geti stats expired_keys] 0
|
||||||
assert_equal [r info.getd stats expired_stale_perc] 0
|
assert_equal [r info.getd stats expired_stale_perc] 0
|
||||||
|
|
||||||
|
# check signed and unsigned
|
||||||
|
assert_equal [r info.geti infotest infotest_global] -2
|
||||||
|
assert_equal [r info.getu infotest infotest_uglobal] -2
|
||||||
|
|
||||||
# the above are always 0, try module info that is non-zero
|
# the above are always 0, try module info that is non-zero
|
||||||
assert_equal [r info.geti infotest_italian infotest_due] 2
|
assert_equal [r info.geti infotest_italian infotest_due] 2
|
||||||
set tre [r info.getd infotest_italian infotest_tre]
|
set tre [r info.getd infotest_italian infotest_tre]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user