| 1773 | } |
| 1774 | |
| 1775 | void scriptCommand(client *c) { |
| 1776 | if (c->argc == 2 && !strcasecmp((const char*)ptrFromObj(c->argv[1]),"help")) { |
| 1777 | const char *help[] = { |
| 1778 | "DEBUG (YES|SYNC|NO)", |
| 1779 | " Set the debug mode for subsequent scripts executed.", |
| 1780 | "EXISTS <sha1> [<sha1> ...]", |
| 1781 | " Return information about the existence of the scripts in the script cache.", |
| 1782 | "FLUSH [ASYNC|SYNC]", |
| 1783 | " Flush the Lua scripts cache. Very dangerous on replicas.", |
| 1784 | " When called without the optional mode argument, the behavior is determined by the", |
| 1785 | " lazyfree-lazy-user-flush configuration directive. Valid modes are:", |
| 1786 | " * ASYNC: Asynchronously flush the scripts cache.", |
| 1787 | " * SYNC: Synchronously flush the scripts cache.", |
| 1788 | "KILL", |
| 1789 | " Kill the currently executing Lua script.", |
| 1790 | "LOAD <script>", |
| 1791 | " Load a script into the scripts cache without executing it.", |
| 1792 | NULL |
| 1793 | }; |
| 1794 | addReplyHelp(c, help); |
| 1795 | } else if (c->argc >= 2 && !strcasecmp(szFromObj(c->argv[1]),"flush")) { |
| 1796 | int async = 0; |
| 1797 | if (c->argc == 3 && !strcasecmp(szFromObj(c->argv[2]),"sync")) { |
| 1798 | async = 0; |
| 1799 | } else if (c->argc == 3 && !strcasecmp(szFromObj(c->argv[2]),"async")) { |
| 1800 | async = 1; |
| 1801 | } else if (c->argc == 2) { |
| 1802 | async = g_pserver->lazyfree_lazy_user_flush ? 1 : 0; |
| 1803 | } else { |
| 1804 | addReplyError(c,"SCRIPT FLUSH only support SYNC|ASYNC option"); |
| 1805 | return; |
| 1806 | } |
| 1807 | scriptingReset(async); |
| 1808 | addReply(c,shared.ok); |
| 1809 | replicationScriptCacheFlush(); |
| 1810 | g_pserver->dirty++; /* Propagating this command is a good idea. */ |
| 1811 | } else if (c->argc >= 2 && !strcasecmp((const char*)ptrFromObj(c->argv[1]),"exists")) { |
| 1812 | int j; |
| 1813 | |
| 1814 | addReplyArrayLen(c, c->argc-2); |
| 1815 | for (j = 2; j < c->argc; j++) { |
| 1816 | if (dictFind(g_pserver->lua_scripts,ptrFromObj(c->argv[j]))) |
| 1817 | addReply(c,shared.cone); |
| 1818 | else |
| 1819 | addReply(c,shared.czero); |
| 1820 | } |
| 1821 | } else if (c->argc == 3 && !strcasecmp((const char*)ptrFromObj(c->argv[1]),"load")) { |
| 1822 | sds sha = luaCreateFunction(c,g_pserver->lua,c->argv[2]); |
| 1823 | if (sha == NULL) return; /* The error was sent by luaCreateFunction(). */ |
| 1824 | addReplyBulkCBuffer(c,sha,40); |
| 1825 | forceCommandPropagation(c,PROPAGATE_REPL|PROPAGATE_AOF); |
| 1826 | } else if (c->argc == 2 && !strcasecmp((const char*)ptrFromObj(c->argv[1]),"kill")) { |
| 1827 | if (g_pserver->lua_caller == NULL) { |
| 1828 | addReplyError(c,"-NOTBUSY No scripts in execution right now."); |
| 1829 | } else if (g_pserver->lua_caller->flags & CLIENT_MASTER) { |
| 1830 | addReplyError(c,"-UNKILLABLE The busy script was sent by a master instance in the context of replication and cannot be killed."); |
| 1831 | } else if (g_pserver->lua_write_dirty) { |
| 1832 | addReplyError(c,"-UNKILLABLE Sorry the script already executed write commands against the dataset. You can either wait the script termination or kill the server in a hard way using the SHUTDOWN NOSAVE command."); |
nothing calls this directly
no test coverage detected