Define a Lua function with the specified body. * The function name will be generated in the following form: * * f_ * * The function increments the reference count of the 'body' object as a * side effect of a successful call. * * On success a pointer to an SDS string representing the function SHA1 of the * just added function is returned (and will be valid until the next ca
| 1403 | * If 'c' is not NULL, on error the client is informed with an appropriate |
| 1404 | * error describing the nature of the problem and the Lua interpreter error. */ |
| 1405 | sds luaCreateFunction(client *c, lua_State *lua, robj *body) { |
| 1406 | char funcname[43]; |
| 1407 | dictEntry *de; |
| 1408 | |
| 1409 | funcname[0] = 'f'; |
| 1410 | funcname[1] = '_'; |
| 1411 | sha1hex(funcname+2,body->ptr,sdslen(body->ptr)); |
| 1412 | |
| 1413 | sds sha = sdsnewlen(funcname+2,40); |
| 1414 | if ((de = dictFind(server.lua_scripts,sha)) != NULL) { |
| 1415 | sdsfree(sha); |
| 1416 | return dictGetKey(de); |
| 1417 | } |
| 1418 | |
| 1419 | sds funcdef = sdsempty(); |
| 1420 | funcdef = sdscat(funcdef,"function "); |
| 1421 | funcdef = sdscatlen(funcdef,funcname,42); |
| 1422 | funcdef = sdscatlen(funcdef,"() ",3); |
| 1423 | funcdef = sdscatlen(funcdef,body->ptr,sdslen(body->ptr)); |
| 1424 | funcdef = sdscatlen(funcdef,"\nend",4); |
| 1425 | |
| 1426 | if (luaL_loadbuffer(lua,funcdef,sdslen(funcdef),"@user_script")) { |
| 1427 | if (c != NULL) { |
| 1428 | addReplyErrorFormat(c, |
| 1429 | "Error compiling script (new function): %s\n", |
| 1430 | lua_tostring(lua,-1)); |
| 1431 | } |
| 1432 | lua_pop(lua,1); |
| 1433 | sdsfree(sha); |
| 1434 | sdsfree(funcdef); |
| 1435 | return NULL; |
| 1436 | } |
| 1437 | sdsfree(funcdef); |
| 1438 | |
| 1439 | if (lua_pcall(lua,0,0,0)) { |
| 1440 | if (c != NULL) { |
| 1441 | addReplyErrorFormat(c,"Error running script (new function): %s\n", |
| 1442 | lua_tostring(lua,-1)); |
| 1443 | } |
| 1444 | lua_pop(lua,1); |
| 1445 | sdsfree(sha); |
| 1446 | return NULL; |
| 1447 | } |
| 1448 | |
| 1449 | /* We also save a SHA1 -> Original script map in a dictionary |
| 1450 | * so that we can replicate / write in the AOF all the |
| 1451 | * EVALSHA commands as EVAL using the original script. */ |
| 1452 | int retval = dictAdd(server.lua_scripts,sha,body); |
| 1453 | serverAssertWithInfo(c ? c : server.lua_client,NULL,retval == DICT_OK); |
| 1454 | server.lua_scripts_mem += sdsZmallocSize(sha) + getStringObjectSdsUsedMemory(body); |
| 1455 | incrRefCount(body); |
| 1456 | return sha; |
| 1457 | } |
| 1458 | |
| 1459 | /* This is the Lua script "count" hook that we use to detect scripts timeout. */ |
| 1460 | void luaMaskCountHook(lua_State *lua, lua_Debug *ar) { |
no test coverage detected