Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
4dd444bb
Commit
4dd444bb
authored
Jul 13, 2011
by
antirez
Browse files
Replicate EVALSHA as EVAL taking a dictionary of sha1 -> script source code.
parent
70ecddc9
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/networking.c
View file @
4dd444bb
...
...
@@ -941,6 +941,9 @@ void clientCommand(redisClient *c) {
}
}
/* Rewrite the command vector of the client. All the new objects ref count
* is incremented. The old command vector is freed, and the old objects
* ref count is decremented. */
void
rewriteClientCommandVector
(
redisClient
*
c
,
int
argc
,
...)
{
va_list
ap
;
int
j
;
...
...
@@ -967,3 +970,21 @@ void rewriteClientCommandVector(redisClient *c, int argc, ...) {
redisAssert
(
c
->
cmd
!=
NULL
);
va_end
(
ap
);
}
/* Rewrite a single item in the command vector.
* The new val ref count is incremented, and the old decremented. */
void
rewriteClientCommandArgument
(
redisClient
*
c
,
int
i
,
robj
*
newval
)
{
robj
*
oldval
;
redisAssert
(
i
<
c
->
argc
);
oldval
=
c
->
argv
[
i
];
c
->
argv
[
i
]
=
newval
;
incrRefCount
(
newval
);
decrRefCount
(
oldval
);
/* If this is the command name make sure to fix c->cmd. */
if
(
i
==
0
)
{
c
->
cmd
=
lookupCommand
(
c
->
argv
[
0
]
->
ptr
);
redisAssert
(
c
->
cmd
!=
NULL
);
}
}
src/object.c
View file @
4dd444bb
...
...
@@ -192,6 +192,23 @@ void decrRefCount(void *obj) {
}
}
/* This function set the ref count to zero without freeing the object.
* It is useful in order to pass a new object to functions incrementing
* the ref count of the received object. Example:
*
* functionThatWillIncrementRefCount(resetRefCount(CreateObject(...)));
*
* Otherwise you need to resort to the less elegant pattern:
*
* *obj = createObject(...);
* functionThatWillIncrementRefCount(obj);
* decrRefCount(obj);
*/
robj
*
resetRefCount
(
robj
*
obj
)
{
obj
->
refcount
=
0
;
return
obj
;
}
int
checkType
(
redisClient
*
c
,
robj
*
o
,
int
type
)
{
if
(
o
->
type
!=
type
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
...
...
src/redis.c
View file @
4dd444bb
...
...
@@ -383,7 +383,7 @@ unsigned int dictEncObjHash(const void *key) {
}
}
/* Sets type
and diskstore negative caching
hash table */
/* Sets type hash table */
dictType
setDictType
=
{
dictEncObjHash
,
/* hash function */
NULL
,
/* key dup */
...
...
src/redis.h
View file @
4dd444bb
...
...
@@ -646,8 +646,9 @@ struct redisServer {
int
cluster_enabled
;
clusterState
cluster
;
/* Scripting */
lua_State
*
lua
;
redisClient
*
lua_client
;
lua_State
*
lua
;
/* The Lua interpreter. We use just one for all clients */
redisClient
*
lua_client
;
/* The "fake client" to query Redis from Lua */
dict
*
lua_scripts
;
/* A dictionary of SHA1 -> Lua scripts */
long
long
lua_time_limit
;
long
long
lua_time_start
;
};
...
...
@@ -742,6 +743,7 @@ extern struct sharedObjectsStruct shared;
extern
dictType
setDictType
;
extern
dictType
zsetDictType
;
extern
dictType
clusterNodesDictType
;
extern
dictType
dbDictType
;
extern
double
R_Zero
,
R_PosInf
,
R_NegInf
,
R_Nan
;
dictType
hashDictType
;
...
...
@@ -782,6 +784,7 @@ void *dupClientReplyValue(void *o);
void
getClientsMaxBuffers
(
unsigned
long
*
longest_output_list
,
unsigned
long
*
biggest_input_buffer
);
void
rewriteClientCommandVector
(
redisClient
*
c
,
int
argc
,
...);
void
rewriteClientCommandArgument
(
redisClient
*
c
,
int
i
,
robj
*
newval
);
#ifdef __GNUC__
void
addReplyErrorFormat
(
redisClient
*
c
,
const
char
*
fmt
,
...)
...
...
@@ -821,6 +824,7 @@ void touchWatchedKeysOnFlush(int dbid);
/* Redis object implementation */
void
decrRefCount
(
void
*
o
);
void
incrRefCount
(
robj
*
o
);
robj
*
resetRefCount
(
robj
*
obj
);
void
freeStringObject
(
robj
*
o
);
void
freeListObject
(
robj
*
o
);
void
freeSetObject
(
robj
*
o
);
...
...
src/scripting.c
View file @
4dd444bb
...
...
@@ -251,6 +251,11 @@ void scriptingInit(void) {
lua_State
*
lua
=
lua_open
();
luaL_openlibs
(
lua
);
/* Initialize a dictionary we use to map SHAs to scripts.
* This is useful for replication, as we need to replicate EVALSHA
* as EVAL, so we need to remember the associated script. */
server
.
lua_scripts
=
dictCreate
(
&
dbDictType
,
NULL
);
/* Register the redis commands table and fields */
lua_newtable
(
lua
);
...
...
@@ -455,6 +460,16 @@ void evalGenericCommand(redisClient *c, int evalsha) {
return
;
}
lua_getglobal
(
lua
,
funcname
);
/* We also save a SHA1 -> Original script map in a dictionary
* so that we can replicate / write in the AOF all the
* EVALSHA commands as EVAL using the original script. */
{
int
retval
=
dictAdd
(
server
.
lua_scripts
,
sdsnewlen
(
funcname
+
2
,
40
),
c
->
argv
[
1
]);
redisAssert
(
retval
==
DICT_OK
);
incrRefCount
(
c
->
argv
[
1
]);
}
}
/* Populate the argv and keys table accordingly to the arguments that
...
...
@@ -490,6 +505,25 @@ void evalGenericCommand(redisClient *c, int evalsha) {
selectDb
(
c
,
server
.
lua_client
->
db
->
id
);
/* set DB ID from Lua client */
luaReplyToRedisReply
(
c
,
lua
);
lua_gc
(
lua
,
LUA_GCSTEP
,
1
);
/* If we have slaves attached we want to replicate this command as
* EVAL instead of EVALSHA. We do this also in the AOF as currently there
* is no easy way to propagate a command in a different way in the AOF
* and in the replication link.
*
* IMPROVEMENT POSSIBLE:
* 1) Replicate this command as EVALSHA in the AOF.
* 2) Remember what slave already received a given script, and replicate
* the EVALSHA against this slaves when possible.
*/
if
(
evalsha
)
{
robj
*
script
=
dictFetchValue
(
server
.
lua_scripts
,
c
->
argv
[
1
]
->
ptr
);
redisAssert
(
script
!=
NULL
);
rewriteClientCommandArgument
(
c
,
0
,
resetRefCount
(
createStringObject
(
"EVAL"
,
4
)));
rewriteClientCommandArgument
(
c
,
1
,
script
);
}
}
void
evalCommand
(
redisClient
*
c
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment