Browse Source

Implement synchronous redis call

tags/1.1.2
Vsevolod Stakhov 8 years ago
parent
commit
b49cbdec4a
1 changed files with 109 additions and 14 deletions
  1. 109
    14
      src/lua/lua_redis.c

+ 109
- 14
src/lua/lua_redis.c View File

@@ -56,9 +56,11 @@ end
*/

LUA_FUNCTION_DEF (redis, make_request);
LUA_FUNCTION_DEF (redis, make_request_sync);

static const struct luaL_reg redislib_m[] = {
LUA_INTERFACE_DEF (redis, make_request),
LUA_INTERFACE_DEF (redis, make_request_sync),
{"__tostring", rspamd_lua_class_tostring},
{NULL, NULL}
};
@@ -82,16 +84,16 @@ struct lua_redis_userdata {
};

static void
lua_redis_free_args (struct lua_redis_userdata *ud)
lua_redis_free_args (char **args, guint nargs)
{
guint i;

if (ud->args) {
for (i = 0; i < ud->nargs; i ++) {
g_free (ud->args[i]);
if (args) {
for (i = 0; i < nargs; i ++) {
g_free (args[i]);
}

g_free (ud->args);
g_free (args);
}
}

@@ -103,7 +105,7 @@ lua_redis_fin (void *arg)
if (ud->ctx) {
ud->terminated = 1;
redisAsyncFree (ud->ctx);
lua_redis_free_args (ud);
lua_redis_free_args (ud->args, ud->nargs);
event_del (&ud->timeout);
luaL_unref (ud->L, LUA_REGISTRYINDEX, ud->cbref);
}
@@ -250,7 +252,7 @@ lua_redis_timeout (int fd, short what, gpointer u)

static void
lua_redis_parse_args (lua_State *L, gint idx, const gchar *cmd,
struct lua_redis_userdata *ud)
gchar ***pargs, guint *nargs)
{
gchar **args = NULL;
gint top;
@@ -287,8 +289,8 @@ lua_redis_parse_args (lua_State *L, gint idx, const gchar *cmd,
top = 1;
}

ud->nargs = top;
ud->args = args;
*pargs = args;
*nargs = top;
}

static void
@@ -374,7 +376,7 @@ lua_redis_make_request (lua_State *L)
ud->L = L;
ud->cbref = cbref;
lua_pushstring (L, "args");
lua_redis_parse_args (L, -1, cmd, ud);
lua_redis_parse_args (L, -1, cmd, &ud->args, &ud->nargs);
ret = TRUE;
}
else {
@@ -404,10 +406,10 @@ lua_redis_make_request (lua_State *L)

cmd = luaL_checkstring (L, 4);
if (top > 4) {
lua_redis_parse_args (L, 5, cmd, ud);
lua_redis_parse_args (L, 5, cmd, &ud->args, &ud->nargs);
}
else {
lua_redis_parse_args (L, 0, cmd, ud);
lua_redis_parse_args (L, 0, cmd, &ud->args, &ud->nargs);
}

ret = TRUE;
@@ -426,7 +428,7 @@ lua_redis_make_request (lua_State *L)
if (ud->ctx == NULL || ud->ctx->err) {
ud->terminated = 1;
redisAsyncFree (ud->ctx);
lua_redis_free_args (ud);
lua_redis_free_args (ud->args, ud->nargs);
luaL_unref (ud->L, LUA_REGISTRYINDEX, ud->cbref);
lua_pushboolean (L, FALSE);

@@ -453,7 +455,7 @@ lua_redis_make_request (lua_State *L)
else {
msg_info ("call to redis failed: %s", ud->ctx->errstr);
ud->terminated = 1;
lua_redis_free_args (ud);
lua_redis_free_args (ud->args, ud->nargs);
redisAsyncFree (ud->ctx);
luaL_unref (ud->L, LUA_REGISTRYINDEX, ud->cbref);
}
@@ -463,6 +465,90 @@ lua_redis_make_request (lua_State *L)

return 1;
}

/***
* @function rspamd_redis.make_request_sync({params})
* Make blocking request to redis server, params is a table of key=value arguments in any order
* @param {task} task worker task object
* @param {ip} host server address
* @param {string} cmd command to be sent to redis
* @param {table} args numeric array of strings used as redis arguments
* @param {number} timeout timeout in seconds for request (1.0 by default)
* @return {boolean + result} `true` and a result if a request has been successful
*/
static int
lua_redis_make_request_sync (lua_State *L)
{
struct rspamd_lua_ip *addr = NULL;
const gchar *cmd = NULL;
struct timeval tv;
gboolean ret = FALSE;
gdouble timeout = REDIS_DEFAULT_TIMEOUT;
gchar **args = NULL;
guint nargs = 0;
redisContext *ctx;
redisReply *r;

if (lua_istable (L, 1)) {

lua_pushstring (L, "cmd");
lua_gettable (L, -2);
cmd = lua_tostring (L, -1);
lua_pop (L, 1);

lua_pushstring (L, "host");
lua_gettable (L, -2);
if (lua_type (L, -1) == LUA_TUSERDATA) {
addr = lua_check_ip (L, -1);
}
lua_pop (L, 1);

lua_pushstring (L, "timeout");
lua_gettable (L, -2);
timeout = lua_tonumber (L, -1);
lua_pop (L, 1);

lua_pushstring (L, "args");
lua_redis_parse_args (L, -1, cmd, &args, &nargs);
ret = TRUE;
}

if (ret) {
msec_to_tv (timeout, &tv);
ctx = redisConnectWithTimeout (rspamd_inet_address_to_string (addr->addr),
rspamd_inet_address_get_port (addr->addr), tv);

if (ctx == NULL || ctx->err) {
redisFree (ctx);
lua_redis_free_args (args, nargs);
lua_pushboolean (L, FALSE);

return 1;
}

r = redisCommandArgv (ctx,
nargs,
(const gchar **)args,
NULL);

if (r != NULL) {
lua_pushboolean (L, TRUE);
lua_redis_push_reply (L, r);
freeReplyObject (r);
redisFree (ctx);

return 2;
}
else {
msg_info ("call to redis failed: %s", ctx->errstr);
redisFree (ctx);
lua_redis_free_args (args, nargs);
lua_pushboolean (L, FALSE);
}
}

return 1;
}
#else
static int
lua_redis_make_request (lua_State *L)
@@ -473,6 +559,15 @@ lua_redis_make_request (lua_State *L)

return 1;
}
static int
lua_redis_make_request_sync (lua_State *L)
{
msg_warn ("rspamd is compiled with no redis support");

lua_pushboolean (L, FALSE);

return 1;
}
#endif

static gint

Loading…
Cancel
Save