diff options
author | antirez <antirez@gmail.com> | 2012-03-20 17:32:48 +0100 |
---|---|---|
committer | antirez <antirez@gmail.com> | 2012-03-20 17:32:48 +0100 |
commit | f3fd419fc95e78818f9eeef15eb2d2e5a60bfbbb (patch) | |
tree | 03e75d79523ef181aaf689de2ea4d0e78af73169 /src/scripting.c | |
parent | 7a0c72f34550c3811324464661f1b463ccfd362b (diff) | |
download | redis-f3fd419fc95e78818f9eeef15eb2d2e5a60bfbbb.tar.gz |
Support for read-only slaves. Semantical fixes.
This commit introduces support for read only slaves via redis.conf and CONFIG GET/SET commands. Also various semantical fixes are implemented here:
1) MULTI/EXEC with only read commands now work where the server is into a state where writes (or commands increasing memory usage) are not allowed. Before this patch everything inside a transaction would fail in this conditions.
2) Scripts just calling read-only commands will work against read only
slaves, when the server is out of memory, or when persistence is into an
error condition. Before the patch EVAL always failed in this condition.
Diffstat (limited to 'src/scripting.c')
-rw-r--r-- | src/scripting.c | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/src/scripting.c b/src/scripting.c index ce1f0877b..e38d08077 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -206,15 +206,45 @@ int luaRedisGenericCommand(lua_State *lua, int raise_error) { goto cleanup; } + /* There are commands that are not allowed inside scripts. */ if (cmd->flags & REDIS_CMD_NOSCRIPT) { luaPushError(lua, "This Redis command is not allowed from scripts"); goto cleanup; } - if (cmd->flags & REDIS_CMD_WRITE && server.lua_random_dirty) { - luaPushError(lua, - "Write commands not allowed after non deterministic commands"); - goto cleanup; + /* Write commands are forbidden against read-only slaves, or if a + * command marked as non-deterministic was already called in the context + * of this script. */ + if (cmd->flags & REDIS_CMD_WRITE) { + if (server.lua_random_dirty) { + luaPushError(lua, + "Write commands not allowed after non deterministic commands"); + goto cleanup; + } else if (server.masterhost && server.repl_slave_ro && + !(server.lua_caller->flags & REDIS_MASTER)) + { + luaPushError(lua, shared.roslaveerr->ptr); + goto cleanup; + } else if (server.stop_writes_on_bgsave_err && + server.saveparamslen > 0 && + server.lastbgsave_status == REDIS_ERR) + { + luaPushError(lua, shared.bgsaveerr->ptr); + goto cleanup; + } + } + + /* If we reached the memory limit configured via maxmemory, commands that + * could enlarge the memory usage are not allowed, but only if this is the + * first write in the context of this script, otherwise we can't stop + * in the middle. */ + if (server.maxmemory && server.lua_write_dirty == 0 && + (cmd->flags & REDIS_CMD_DENYOOM)) + { + if (freeMemoryIfNeeded() == REDIS_ERR) { + luaPushError(lua, shared.oomerr->ptr); + goto cleanup; + } } if (cmd->flags & REDIS_CMD_RANDOM) server.lua_random_dirty = 1; |