From 3dc84c530063e2ebd4f975e4066dd834cd6cbe9f Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 3 Oct 2016 00:08:35 +0200 Subject: Modules: API to save/load single precision floating point numbers. When double precision is not needed, to take 2x space in the serialization is not good. --- src/module.c | 27 +++++++++++++++++++++++++++ src/rdb.c | 17 +++++++++++++++-- src/rdb.h | 2 ++ src/redismodule.h | 4 ++++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/module.c b/src/module.c index ab63f8b04..e7594c166 100644 --- a/src/module.c +++ b/src/module.c @@ -2849,6 +2849,31 @@ double RM_LoadDouble(RedisModuleIO *io) { return value; } +/* In the context of the rdb_save method of a module data type, saves a float + * value to the RDB file. The float can be a valid number, a NaN or infinity. + * It is possible to load back the value with RedisModule_LoadFloat(). */ +void RM_SaveFloat(RedisModuleIO *io, float value) { + if (io->error) return; + int retval = rdbSaveBinaryFloatValue(io->rio, value); + if (retval == -1) { + io->error = 1; + } else { + io->bytes += retval; + } +} + +/* In the context of the rdb_save method of a module data type, loads back the + * float value saved by RedisModule_SaveFloat(). */ +float RM_LoadFloat(RedisModuleIO *io) { + float value; + int retval = rdbLoadBinaryFloatValue(io->rio, &value); + if (retval == -1) { + moduleRDBLoadError(io); + return 0; /* Never reached. */ + } + return value; +} + /* -------------------------------------------------------------------------- * AOF API for modules data types * -------------------------------------------------------------------------- */ @@ -3280,6 +3305,8 @@ void moduleRegisterCoreAPI(void) { REGISTER_API(LoadStringBuffer); REGISTER_API(SaveDouble); REGISTER_API(LoadDouble); + REGISTER_API(SaveFloat); + REGISTER_API(LoadFloat); REGISTER_API(EmitAOF); REGISTER_API(Log); REGISTER_API(LogIOError); diff --git a/src/rdb.c b/src/rdb.c index 5e03dbab5..252044344 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -567,17 +567,30 @@ int rdbLoadDoubleValue(rio *rdb, double *val) { * Return -1 on error, the size of the serialized value on success. */ int rdbSaveBinaryDoubleValue(rio *rdb, double val) { memrev64ifbe(&val); - return rdbWriteRaw(rdb,&val,8); + return rdbWriteRaw(rdb,&val,sizeof(val)); } /* Loads a double from RDB 8 or greater. See rdbSaveBinaryDoubleValue() for * more info. On error -1 is returned, otherwise 0. */ int rdbLoadBinaryDoubleValue(rio *rdb, double *val) { - if (rioRead(rdb,val,8) == 0) return -1; + if (rioRead(rdb,val,sizeof(*val)) == 0) return -1; memrev64ifbe(val); return 0; } +/* Like rdbSaveBinaryDoubleValue() but single precision. */ +int rdbSaveBinaryFloatValue(rio *rdb, float val) { + memrev32ifbe(&val); + return rdbWriteRaw(rdb,&val,sizeof(val)); +} + +/* Like rdbLoadBinaryDoubleValue() but single precision. */ +int rdbLoadBinaryFloatValue(rio *rdb, float *val) { + if (rioRead(rdb,val,sizeof(*val)) == 0) return -1; + memrev32ifbe(val); + return 0; +} + /* Save the object type of object "o". */ int rdbSaveObjectType(rio *rdb, robj *o) { switch (o->type) { diff --git a/src/rdb.h b/src/rdb.h index cd1d65392..60c52a7c1 100644 --- a/src/rdb.h +++ b/src/rdb.h @@ -134,6 +134,8 @@ ssize_t rdbSaveRawString(rio *rdb, unsigned char *s, size_t len); void *rdbGenericLoadStringObject(rio *rdb, int flags, size_t *lenptr); int rdbSaveBinaryDoubleValue(rio *rdb, double val); int rdbLoadBinaryDoubleValue(rio *rdb, double *val); +int rdbSaveBinaryFloatValue(rio *rdb, float val); +int rdbLoadBinaryFloatValue(rio *rdb, float *val); int rdbLoadRio(rio *rdb); #endif diff --git a/src/redismodule.h b/src/redismodule.h index dcc0aa1ea..346110090 100644 --- a/src/redismodule.h +++ b/src/redismodule.h @@ -184,6 +184,8 @@ RedisModuleString *REDISMODULE_API_FUNC(RedisModule_LoadString)(RedisModuleIO *i char *REDISMODULE_API_FUNC(RedisModule_LoadStringBuffer)(RedisModuleIO *io, size_t *lenptr); void REDISMODULE_API_FUNC(RedisModule_SaveDouble)(RedisModuleIO *io, double value); double REDISMODULE_API_FUNC(RedisModule_LoadDouble)(RedisModuleIO *io); +void REDISMODULE_API_FUNC(RedisModule_SaveFloat)(RedisModuleIO *io, float value); +float REDISMODULE_API_FUNC(RedisModule_LoadFloat)(RedisModuleIO *io); void REDISMODULE_API_FUNC(RedisModule_Log)(RedisModuleCtx *ctx, const char *level, const char *fmt, ...); void REDISMODULE_API_FUNC(RedisModule_LogIOError)(RedisModuleIO *io, const char *levelstr, const char *fmt, ...); int REDISMODULE_API_FUNC(RedisModule_StringAppendBuffer)(RedisModuleCtx *ctx, RedisModuleString *str, const char *buf, size_t len); @@ -281,6 +283,8 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int REDISMODULE_GET_API(LoadStringBuffer); REDISMODULE_GET_API(SaveDouble); REDISMODULE_GET_API(LoadDouble); + REDISMODULE_GET_API(SaveFloat); + REDISMODULE_GET_API(LoadFloat); REDISMODULE_GET_API(EmitAOF); REDISMODULE_GET_API(Log); REDISMODULE_GET_API(LogIOError); -- cgit v1.2.1