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.
This commit is contained in:
antirez 2017-11-29 16:38:16 +01:00
parent 28dfdca733
commit 452ad2e928
2 changed files with 19 additions and 30 deletions

View File

@ -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. */

View File

@ -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);