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
| 1416 | * If 'c' is not NULL, on error the client is informed with an appropriate |
| 1417 | * error describing the nature of the problem and the Lua interpreter error. */ |
| 1418 | sds luaCreateFunction(client *c, lua_State *lua, robj *body) { |
| 1419 | char funcname[43]; |
| 1420 | dictEntry *de; |
| 1421 | |
| 1422 | funcname[0] = 'f'; |
| 1423 | funcname[1] = '_'; |
| 1424 | sha1hex(funcname+2,(char*)ptrFromObj(body),sdslen((sds)ptrFromObj(body))); |
| 1425 | |
| 1426 | sds sha = sdsnewlen(funcname+2,40); |
| 1427 | if ((de = dictFind(g_pserver->lua_scripts,sha)) != NULL) { |
| 1428 | sdsfree(sha); |
| 1429 | return (sds)dictGetKey(de); |
| 1430 | } |
| 1431 | |
| 1432 | sds funcdef = sdsempty(); |
| 1433 | funcdef = sdscat(funcdef,"function "); |
| 1434 | funcdef = sdscatlen(funcdef,funcname,42); |
| 1435 | funcdef = sdscatlen(funcdef,"() ",3); |
| 1436 | funcdef = sdscatlen(funcdef,ptrFromObj(body),sdslen((sds)ptrFromObj(body))); |
| 1437 | funcdef = sdscatlen(funcdef,"\nend",4); |
| 1438 | |
| 1439 | if (luaL_loadbuffer(lua,funcdef,sdslen(funcdef),"@user_script")) { |
| 1440 | if (c != NULL) { |
| 1441 | addReplyErrorFormat(c, |
| 1442 | "Error compiling script (new function): %s\n", |
| 1443 | lua_tostring(lua,-1)); |
| 1444 | } |
| 1445 | lua_pop(lua,1); |
| 1446 | sdsfree(sha); |
| 1447 | sdsfree(funcdef); |
| 1448 | return NULL; |
| 1449 | } |
| 1450 | sdsfree(funcdef); |
| 1451 | |
| 1452 | if (lua_pcall(lua,0,0,0)) { |
| 1453 | if (c != NULL) { |
| 1454 | addReplyErrorFormat(c,"Error running script (new function): %s\n", |
| 1455 | lua_tostring(lua,-1)); |
| 1456 | } |
| 1457 | lua_pop(lua,1); |
| 1458 | sdsfree(sha); |
| 1459 | return NULL; |
| 1460 | } |
| 1461 | |
| 1462 | /* We also save a SHA1 -> Original script map in a dictionary |
| 1463 | * so that we can replicate / write in the AOF all the |
| 1464 | * EVALSHA commands as EVAL using the original script. */ |
| 1465 | int retval = dictAdd(g_pserver->lua_scripts,sha,body); |
| 1466 | serverAssertWithInfo(c ? c : serverTL->lua_client,NULL,retval == DICT_OK); |
| 1467 | g_pserver->lua_scripts_mem += sdsZmallocSize(sha) + getStringObjectSdsUsedMemory(body); |
| 1468 | incrRefCount(body); |
| 1469 | return sha; |
| 1470 | } |
| 1471 | |
| 1472 | /* This is the Lua script "count" hook that we use to detect scripts timeout. */ |
| 1473 | void luaMaskCountHook(lua_State *lua, lua_Debug *ar) { |
no test coverage detected