Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
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) {
...
@@ -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
,
...)
{
void
rewriteClientCommandVector
(
redisClient
*
c
,
int
argc
,
...)
{
va_list
ap
;
va_list
ap
;
int
j
;
int
j
;
...
@@ -967,3 +970,21 @@ void rewriteClientCommandVector(redisClient *c, int argc, ...) {
...
@@ -967,3 +970,21 @@ void rewriteClientCommandVector(redisClient *c, int argc, ...) {
redisAssert
(
c
->
cmd
!=
NULL
);
redisAssert
(
c
->
cmd
!=
NULL
);
va_end
(
ap
);
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) {
...
@@ -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
)
{
int
checkType
(
redisClient
*
c
,
robj
*
o
,
int
type
)
{
if
(
o
->
type
!=
type
)
{
if
(
o
->
type
!=
type
)
{
addReply
(
c
,
shared
.
wrongtypeerr
);
addReply
(
c
,
shared
.
wrongtypeerr
);
...
...
src/redis.c
View file @
4dd444bb
...
@@ -383,7 +383,7 @@ unsigned int dictEncObjHash(const void *key) {
...
@@ -383,7 +383,7 @@ unsigned int dictEncObjHash(const void *key) {
}
}
}
}
/* Sets type
and diskstore negative caching
hash table */
/* Sets type hash table */
dictType
setDictType
=
{
dictType
setDictType
=
{
dictEncObjHash
,
/* hash function */
dictEncObjHash
,
/* hash function */
NULL
,
/* key dup */
NULL
,
/* key dup */
...
...
src/redis.h
View file @
4dd444bb
...
@@ -646,8 +646,9 @@ struct redisServer {
...
@@ -646,8 +646,9 @@ struct redisServer {
int
cluster_enabled
;
int
cluster_enabled
;
clusterState
cluster
;
clusterState
cluster
;
/* Scripting */
/* Scripting */
lua_State
*
lua
;
lua_State
*
lua
;
/* The Lua interpreter. We use just one for all clients */
redisClient
*
lua_client
;
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_limit
;
long
long
lua_time_start
;
long
long
lua_time_start
;
};
};
...
@@ -742,6 +743,7 @@ extern struct sharedObjectsStruct shared;
...
@@ -742,6 +743,7 @@ extern struct sharedObjectsStruct shared;
extern
dictType
setDictType
;
extern
dictType
setDictType
;
extern
dictType
zsetDictType
;
extern
dictType
zsetDictType
;
extern
dictType
clusterNodesDictType
;
extern
dictType
clusterNodesDictType
;
extern
dictType
dbDictType
;
extern
double
R_Zero
,
R_PosInf
,
R_NegInf
,
R_Nan
;
extern
double
R_Zero
,
R_PosInf
,
R_NegInf
,
R_Nan
;
dictType
hashDictType
;
dictType
hashDictType
;
...
@@ -782,6 +784,7 @@ void *dupClientReplyValue(void *o);
...
@@ -782,6 +784,7 @@ void *dupClientReplyValue(void *o);
void
getClientsMaxBuffers
(
unsigned
long
*
longest_output_list
,
void
getClientsMaxBuffers
(
unsigned
long
*
longest_output_list
,
unsigned
long
*
biggest_input_buffer
);
unsigned
long
*
biggest_input_buffer
);
void
rewriteClientCommandVector
(
redisClient
*
c
,
int
argc
,
...);
void
rewriteClientCommandVector
(
redisClient
*
c
,
int
argc
,
...);
void
rewriteClientCommandArgument
(
redisClient
*
c
,
int
i
,
robj
*
newval
);
#ifdef __GNUC__
#ifdef __GNUC__
void
addReplyErrorFormat
(
redisClient
*
c
,
const
char
*
fmt
,
...)
void
addReplyErrorFormat
(
redisClient
*
c
,
const
char
*
fmt
,
...)
...
@@ -821,6 +824,7 @@ void touchWatchedKeysOnFlush(int dbid);
...
@@ -821,6 +824,7 @@ void touchWatchedKeysOnFlush(int dbid);
/* Redis object implementation */
/* Redis object implementation */
void
decrRefCount
(
void
*
o
);
void
decrRefCount
(
void
*
o
);
void
incrRefCount
(
robj
*
o
);
void
incrRefCount
(
robj
*
o
);
robj
*
resetRefCount
(
robj
*
obj
);
void
freeStringObject
(
robj
*
o
);
void
freeStringObject
(
robj
*
o
);
void
freeListObject
(
robj
*
o
);
void
freeListObject
(
robj
*
o
);
void
freeSetObject
(
robj
*
o
);
void
freeSetObject
(
robj
*
o
);
...
...
src/scripting.c
View file @
4dd444bb
...
@@ -251,6 +251,11 @@ void scriptingInit(void) {
...
@@ -251,6 +251,11 @@ void scriptingInit(void) {
lua_State
*
lua
=
lua_open
();
lua_State
*
lua
=
lua_open
();
luaL_openlibs
(
lua
);
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 */
/* Register the redis commands table and fields */
lua_newtable
(
lua
);
lua_newtable
(
lua
);
...
@@ -455,6 +460,16 @@ void evalGenericCommand(redisClient *c, int evalsha) {
...
@@ -455,6 +460,16 @@ void evalGenericCommand(redisClient *c, int evalsha) {
return
;
return
;
}
}
lua_getglobal
(
lua
,
funcname
);
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
/* Populate the argv and keys table accordingly to the arguments that
...
@@ -490,6 +505,25 @@ void evalGenericCommand(redisClient *c, int evalsha) {
...
@@ -490,6 +505,25 @@ void evalGenericCommand(redisClient *c, int evalsha) {
selectDb
(
c
,
server
.
lua_client
->
db
->
id
);
/* set DB ID from Lua client */
selectDb
(
c
,
server
.
lua_client
->
db
->
id
);
/* set DB ID from Lua client */
luaReplyToRedisReply
(
c
,
lua
);
luaReplyToRedisReply
(
c
,
lua
);
lua_gc
(
lua
,
LUA_GCSTEP
,
1
);
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
)
{
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