summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2017-11-29 16:38:16 +0100
committerantirez <antirez@gmail.com>2017-11-29 16:41:44 +0100
commit7eefca162ab9e8a637ed56f7ebd459db250d89bd (patch)
treeffa0632eb77ec59aeb442a6e2d025a9c01a49620
parent21acad40eaa5358ca6f31c3af84969fb3445bd20 (diff)
downloadredis-7eefca162ab9e8a637ed56f7ebd459db250d89bd.tar.gz
PSYNC2: just store script bodies into RDB.
Related to #4483. As suggested by @soloestoy, we can retrieve the SHA1 from the body. Given that in the new implementation using AUX fields we ended copying around a lot to create new objects and strings, extremize such concept and trade CPU for space inside the RDB file.
-rw-r--r--src/rdb.c34
-rw-r--r--src/scripting.c15
2 files changed, 19 insertions, 30 deletions
diff --git a/src/rdb.c b/src/rdb.c
index d1495e79a..19ba59ab8 100644
--- a/src/rdb.c
+++ b/src/rdb.c
@@ -950,16 +950,9 @@ int rdbSaveRio(rio *rdb, int *error, int flags, rdbSaveInfo *rsi) {
if (rsi && dictSize(server.lua_scripts)) {
di = dictGetIterator(server.lua_scripts);
while((de = dictNext(di)) != NULL) {
- sds sha = dictGetKey(de);
robj *body = dictGetVal(de);
- /* Concatenate the SHA1 and the Lua script together. Because the
- * SHA1 is fixed length, we will always be able to load it back
- * telling apart the name from the body. */
- sds combo = sdsdup(sha);
- combo = sdscatlen(combo,body->ptr,sdslen(body->ptr));
- if (rdbSaveAuxField(rdb,"lua",3,combo,sdslen(combo)) == -1)
+ if (rdbSaveAuxField(rdb,"lua",3,body->ptr,sdslen(body->ptr)) == -1)
goto werr;
- sdsfree(combo);
}
dictReleaseIterator(di);
}
@@ -1611,31 +1604,12 @@ int rdbLoadRio(rio *rdb, rdbSaveInfo *rsi) {
} else if (!strcasecmp(auxkey->ptr,"repl-offset")) {
if (rsi) rsi->repl_offset = strtoll(auxval->ptr,NULL,10);
} else if (!strcasecmp(auxkey->ptr,"lua")) {
- /* Load the string combining the function name and body
- * back in memory. The format is basically:
- * <sha><lua-script-bodybody>. To load it back we need
- * to create the function name as "f_<sha>" and load the
- * body as a Redis string object. */
- sds combo = auxval->ptr;
- if (sdslen(combo) < 40) {
- rdbExitReportCorruptRDB(
- "Lua script stored into the RDB file has invalid "
- "length < 40 bytes: '%s'", combo);
- }
- char funcname[42];
- funcname[0] = 'f';
- funcname[1] = '_';
- memcpy(funcname+2,combo,40);
- robj *body = createRawStringObject(combo+40,sdslen(combo)-40);
-
- /* Register the function. */
- if (luaCreateFunction(NULL,server.lua,funcname,body) == C_ERR) {
+ /* Load the script back in memory. */
+ if (luaCreateFunction(NULL,server.lua,NULL,auxval) == C_ERR) {
rdbExitReportCorruptRDB(
"Can't load Lua script from RDB file! "
- "Script SHA1: %.42s BODY: %s",
- combo, combo+42);
+ "BODY: %s", auxval->ptr);
}
- decrRefCount(body);
} else {
/* We ignore fields we don't understand, as by AUX field
* contract. */
diff --git a/src/scripting.c b/src/scripting.c
index 64de1edcd..1ef91a4de 100644
--- a/src/scripting.c
+++ b/src/scripting.c
@@ -1147,11 +1147,26 @@ int redis_math_randomseed (lua_State *L) {
*
* f_<hex sha1 sum>
*
+ * If 'funcname' is NULL, the function name is created by the function
+ * on the fly doing the SHA1 of the body, this means that passing the funcname
+ * is just an optimization in case it's already at hand.
+ *
+ * The function increments the reference count of the 'body' object as a
+ * side effect of a successful call.
+ *
* On success C_OK is returned, and nothing is left on the Lua stack.
* On error C_ERR is returned and an appropriate error is set in the
* client context. */
int luaCreateFunction(client *c, lua_State *lua, char *funcname, robj *body) {
sds funcdef = sdsempty();
+ char fname[42];
+
+ if (funcname == NULL) {
+ fname[0] = 'f';
+ fname[1] = '_';
+ sha1hex(fname+2,body->ptr,sdslen(body->ptr));
+ funcname = fname;
+ }
funcdef = sdscat(funcdef,"function ");
funcdef = sdscatlen(funcdef,funcname,42);