mirror of
https://github.com/fluencelabs/redis
synced 2025-03-31 14:51:04 +00:00
Lua math.random and math.randomseed replaced with our own version based on redisSrand48(). Seed initialized to the same value at every EVAL/EVALSHA call.
This commit is contained in:
parent
69786b262d
commit
e108bab043
@ -129,7 +129,7 @@ replication.o: replication.c redis.h fmacros.h config.h ae.h sds.h dict.h \
|
|||||||
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
|
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h
|
||||||
scripting.o: scripting.c redis.h fmacros.h config.h ae.h sds.h dict.h \
|
scripting.o: scripting.c redis.h fmacros.h config.h ae.h sds.h dict.h \
|
||||||
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h \
|
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h util.h \
|
||||||
sha1.h
|
sha1.h rand.h
|
||||||
rio.o: rio.c sds.h
|
rio.o: rio.c sds.h
|
||||||
sds.o: sds.c sds.h zmalloc.h
|
sds.o: sds.c sds.h zmalloc.h
|
||||||
sha1.o: sha1.c sha1.h config.h
|
sha1.o: sha1.c sha1.h config.h
|
||||||
|
@ -1,16 +1,20 @@
|
|||||||
#include "redis.h"
|
#include "redis.h"
|
||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
|
#include "rand.h"
|
||||||
|
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
#include <lauxlib.h>
|
#include <lauxlib.h>
|
||||||
#include <lualib.h>
|
#include <lualib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
char *redisProtocolToLuaType_Int(lua_State *lua, char *reply);
|
char *redisProtocolToLuaType_Int(lua_State *lua, char *reply);
|
||||||
char *redisProtocolToLuaType_Bulk(lua_State *lua, char *reply);
|
char *redisProtocolToLuaType_Bulk(lua_State *lua, char *reply);
|
||||||
char *redisProtocolToLuaType_Status(lua_State *lua, char *reply);
|
char *redisProtocolToLuaType_Status(lua_State *lua, char *reply);
|
||||||
char *redisProtocolToLuaType_Error(lua_State *lua, char *reply);
|
char *redisProtocolToLuaType_Error(lua_State *lua, char *reply);
|
||||||
char *redisProtocolToLuaType_MultiBulk(lua_State *lua, char *reply);
|
char *redisProtocolToLuaType_MultiBulk(lua_State *lua, char *reply);
|
||||||
|
int redis_math_random (lua_State *L);
|
||||||
|
int redis_math_randomseed (lua_State *L);
|
||||||
|
|
||||||
/* Take a Redis reply in the Redis protocol format and convert it into a
|
/* Take a Redis reply in the Redis protocol format and convert it into a
|
||||||
* Lua type. Thanks to this function, and the introduction of not connected
|
* Lua type. Thanks to this function, and the introduction of not connected
|
||||||
@ -288,6 +292,19 @@ void scriptingInit(void) {
|
|||||||
/* Finally set the table as 'redis' global var. */
|
/* Finally set the table as 'redis' global var. */
|
||||||
lua_setglobal(lua,"redis");
|
lua_setglobal(lua,"redis");
|
||||||
|
|
||||||
|
/* Replace math.random and math.randomseed with our implementations. */
|
||||||
|
lua_getglobal(lua,"math");
|
||||||
|
|
||||||
|
lua_pushstring(lua,"random");
|
||||||
|
lua_pushcfunction(lua,redis_math_random);
|
||||||
|
lua_settable(lua,-3);
|
||||||
|
|
||||||
|
lua_pushstring(lua,"randomseed");
|
||||||
|
lua_pushcfunction(lua,redis_math_randomseed);
|
||||||
|
lua_settable(lua,-3);
|
||||||
|
|
||||||
|
lua_setglobal(lua,"math");
|
||||||
|
|
||||||
/* Create the (non connected) client that we use to execute Redis commands
|
/* Create the (non connected) client that we use to execute Redis commands
|
||||||
* inside the Lua interpreter */
|
* inside the Lua interpreter */
|
||||||
server.lua_client = createClient(-1);
|
server.lua_client = createClient(-1);
|
||||||
@ -398,6 +415,10 @@ void evalGenericCommand(redisClient *c, int evalsha) {
|
|||||||
char funcname[43];
|
char funcname[43];
|
||||||
long long numkeys;
|
long long numkeys;
|
||||||
|
|
||||||
|
/* We want the same PRNG sequence at every call so that our PRNG is
|
||||||
|
* not affected by external state. */
|
||||||
|
redisSrand48(0);
|
||||||
|
|
||||||
/* Get the number of arguments that are keys */
|
/* Get the number of arguments that are keys */
|
||||||
if (getLongLongFromObjectOrReply(c,c->argv[2],&numkeys,NULL) != REDIS_OK)
|
if (getLongLongFromObjectOrReply(c,c->argv[2],&numkeys,NULL) != REDIS_OK)
|
||||||
return;
|
return;
|
||||||
@ -541,3 +562,42 @@ void evalShaCommand(redisClient *c) {
|
|||||||
}
|
}
|
||||||
evalGenericCommand(c,1);
|
evalGenericCommand(c,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We replace math.random() with our implementation that is not affected
|
||||||
|
* by specific libc random() implementations and will output the same sequence
|
||||||
|
* (for the same seed) in every arch. */
|
||||||
|
|
||||||
|
/* The following implementation is the one shipped with Lua itself but with
|
||||||
|
* rand() replaced by redisLrand48(). */
|
||||||
|
int redis_math_random (lua_State *L) {
|
||||||
|
/* the `%' avoids the (rare) case of r==1, and is needed also because on
|
||||||
|
some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
|
||||||
|
lua_Number r = (lua_Number)(redisLrand48()%REDIS_LRAND48_MAX) /
|
||||||
|
(lua_Number)REDIS_LRAND48_MAX;
|
||||||
|
switch (lua_gettop(L)) { /* check number of arguments */
|
||||||
|
case 0: { /* no arguments */
|
||||||
|
lua_pushnumber(L, r); /* Number between 0 and 1 */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: { /* only upper limit */
|
||||||
|
int u = luaL_checkint(L, 1);
|
||||||
|
luaL_argcheck(L, 1<=u, 1, "interval is empty");
|
||||||
|
lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: { /* lower and upper limits */
|
||||||
|
int l = luaL_checkint(L, 1);
|
||||||
|
int u = luaL_checkint(L, 2);
|
||||||
|
luaL_argcheck(L, l<=u, 2, "interval is empty");
|
||||||
|
lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: return luaL_error(L, "wrong number of arguments");
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int redis_math_randomseed (lua_State *L) {
|
||||||
|
redisSrand48(luaL_checkint(L, 1));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user