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
a9b07ac4
Commit
a9b07ac4
authored
Oct 25, 2011
by
antirez
Browse files
SCRIPT LOAD implemented, scripting eval command refactoring.
parent
070e3945
Changes
1
Hide whitespace changes
Inline
Side-by-side
src/scripting.c
View file @
a9b07ac4
...
@@ -488,6 +488,52 @@ void luaSetGlobalArray(lua_State *lua, char *var, robj **elev, int elec) {
...
@@ -488,6 +488,52 @@ void luaSetGlobalArray(lua_State *lua, char *var, robj **elev, int elec) {
lua_setglobal
(
lua
,
var
);
lua_setglobal
(
lua
,
var
);
}
}
/* Define a lua function with the specified function name and body.
* The function name musts be a 2 characters long string, since all the
* functions we defined in the Lua context are in the form:
*
* f_<hex sha1 sum>
*
* On success REDIS_OK is returned, and nothing is left on the Lua stack.
* On error REDIS_ERR is returned and an appropriate error is set in the
* client context. */
int
luaCreateFunction
(
redisClient
*
c
,
lua_State
*
lua
,
char
*
funcname
,
robj
*
body
)
{
sds
funcdef
=
sdsempty
();
lua_pop
(
lua
,
1
);
/* remove the nil from the stack */
funcdef
=
sdscat
(
funcdef
,
"function "
);
funcdef
=
sdscatlen
(
funcdef
,
funcname
,
42
);
funcdef
=
sdscatlen
(
funcdef
,
" ()
\n
"
,
4
);
funcdef
=
sdscatlen
(
funcdef
,
body
->
ptr
,
sdslen
(
body
->
ptr
));
funcdef
=
sdscatlen
(
funcdef
,
"
\n
end
\n
"
,
5
);
if
(
luaL_loadbuffer
(
lua
,
funcdef
,
sdslen
(
funcdef
),
"func definition"
))
{
addReplyErrorFormat
(
c
,
"Error compiling script (new function): %s
\n
"
,
lua_tostring
(
lua
,
-
1
));
lua_pop
(
lua
,
1
);
sdsfree
(
funcdef
);
return
REDIS_ERR
;
}
sdsfree
(
funcdef
);
if
(
lua_pcall
(
lua
,
0
,
0
,
0
))
{
addReplyErrorFormat
(
c
,
"Error running script (new function): %s
\n
"
,
lua_tostring
(
lua
,
-
1
));
lua_pop
(
lua
,
1
);
return
REDIS_ERR
;
}
/* 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
),
body
);
redisAssertWithInfo
(
c
,
NULL
,
retval
==
DICT_OK
);
incrRefCount
(
body
);
}
return
REDIS_OK
;
}
void
evalGenericCommand
(
redisClient
*
c
,
int
evalsha
)
{
void
evalGenericCommand
(
redisClient
*
c
,
int
evalsha
)
{
lua_State
*
lua
=
server
.
lua
;
lua_State
*
lua
=
server
.
lua
;
char
funcname
[
43
];
char
funcname
[
43
];
...
@@ -532,10 +578,9 @@ void evalGenericCommand(redisClient *c, int evalsha) {
...
@@ -532,10 +578,9 @@ void evalGenericCommand(redisClient *c, int evalsha) {
funcname
[
42
]
=
'\0'
;
funcname
[
42
]
=
'\0'
;
}
}
/* Try to lookup the Lua function */
lua_getglobal
(
lua
,
funcname
);
lua_getglobal
(
lua
,
funcname
);
if
(
lua_isnil
(
lua
,
1
))
{
if
(
lua_isnil
(
lua
,
1
))
{
sds
funcdef
;
/* Function not defined... let's define it if we have the
/* Function not defined... let's define it if we have the
* body of the funciton. If this is an EVALSHA call we can just
* body of the funciton. If this is an EVALSHA call we can just
* return an error. */
* return an error. */
...
@@ -544,41 +589,10 @@ void evalGenericCommand(redisClient *c, int evalsha) {
...
@@ -544,41 +589,10 @@ void evalGenericCommand(redisClient *c, int evalsha) {
lua_pop
(
lua
,
1
);
/* remove the nil from the stack */
lua_pop
(
lua
,
1
);
/* remove the nil from the stack */
return
;
return
;
}
}
funcdef
=
sdsempty
();
if
(
luaCreateFunction
(
c
,
lua
,
funcname
,
c
->
argv
[
1
])
==
REDIS_ERR
)
return
;
/* Now the following is guaranteed to return non nil */
lua_pop
(
lua
,
1
);
/* remove the nil from the stack */
funcdef
=
sdscat
(
funcdef
,
"function "
);
funcdef
=
sdscatlen
(
funcdef
,
funcname
,
42
);
funcdef
=
sdscatlen
(
funcdef
,
" ()
\n
"
,
4
);
funcdef
=
sdscatlen
(
funcdef
,
c
->
argv
[
1
]
->
ptr
,
sdslen
(
c
->
argv
[
1
]
->
ptr
));
funcdef
=
sdscatlen
(
funcdef
,
"
\n
end
\n
"
,
5
);
/* printf("Defining:\n%s\n",funcdef); */
if
(
luaL_loadbuffer
(
lua
,
funcdef
,
sdslen
(
funcdef
),
"func definition"
))
{
addReplyErrorFormat
(
c
,
"Error compiling script (new function): %s
\n
"
,
lua_tostring
(
lua
,
-
1
));
lua_pop
(
lua
,
1
);
sdsfree
(
funcdef
);
return
;
}
sdsfree
(
funcdef
);
if
(
lua_pcall
(
lua
,
0
,
0
,
0
))
{
addReplyErrorFormat
(
c
,
"Error running script (new function): %s
\n
"
,
lua_tostring
(
lua
,
-
1
));
lua_pop
(
lua
,
1
);
return
;
}
lua_getglobal
(
lua
,
funcname
);
lua_getglobal
(
lua
,
funcname
);
redisAssert
(
!
lua_isnil
(
lua
,
1
));
/* 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
]);
redisAssertWithInfo
(
c
,
NULL
,
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
...
@@ -709,6 +723,17 @@ void scriptCommand(redisClient *c) {
...
@@ -709,6 +723,17 @@ void scriptCommand(redisClient *c) {
else
else
addReply
(
c
,
shared
.
czero
);
addReply
(
c
,
shared
.
czero
);
}
}
}
else
if
(
c
->
argc
==
3
&&
!
strcasecmp
(
c
->
argv
[
1
]
->
ptr
,
"load"
))
{
/* We obtain the script SHA1, then check if this function is already
* defined into the Lua state */
char
funcname
[
43
];
funcname
[
0
]
=
'f'
;
funcname
[
1
]
=
'_'
;
hashScript
(
funcname
+
2
,
c
->
argv
[
2
]
->
ptr
,
sdslen
(
c
->
argv
[
2
]
->
ptr
));
if
(
luaCreateFunction
(
c
,
server
.
lua
,
funcname
,
c
->
argv
[
2
])
==
REDIS_ERR
)
return
;
addReply
(
c
,
shared
.
ok
);
}
else
{
}
else
{
addReplyError
(
c
,
"Unknown SCRIPT subcommand or wrong # of args."
);
addReplyError
(
c
,
"Unknown SCRIPT subcommand or wrong # of args."
);
}
}
...
...
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