Esempio n. 1
0
static int lconn_get_reply(lua_State * L)
{
  redisContext * pContext = check_connection(L, 1);

  int nret = 0;

  redisReply * pReply = NULL;

  int ok = redisGetReply(pContext, (void **)&pReply);
  if (ok != REDIS_OK || pReply == NULL)
  {
    /* TODO: Shouldn't we clear the context error state somehow after this? */
    return push_error(L, pContext);
  }

  nret = push_reply(L, pReply);

  /*
  * TODO: Not entirely safe: if above code throws error, reply object is leaked.
  */
  freeReplyObject(pReply);
  pReply = NULL;

  return nret;
}
Esempio n. 2
0
static void on_redis_response(redisAsyncContext *context, void *reply, void *privdata)
{
  redisReply *redisReply = reply;
  luv_ref_t *ref = privdata;
  int replyArgsCount = 0;

  lua_State *L = ref->L;
  lua_rawgeti(L, LUA_REGISTRYINDEX, ref->r);
  luaL_unref(L, LUA_REGISTRYINDEX, ref->r);
  ref_free(ref);

  if (redisReply == NULL)
  {
    luv_push_async_hiredis_error(L, context, "on_redis_response");
    lua_pushnil(L);
    luv_acall(L, 2, 0, "on_redis_response");
  }
  else
  {
    if (redisReply->type != REDIS_REPLY_ERROR)
    {
      lua_pushnil(L);
      ++replyArgsCount;
    }
    replyArgsCount += push_reply(L, redisReply);
    luv_acall(L, replyArgsCount, 0, "on_redis_response");
  }
}
Esempio n. 3
0
static int lconn_command(lua_State * L)
{
  redisContext * pContext = check_connection(L, 1);

  const char * argv[LUAHIREDIS_MAXARGS];
  size_t argvlen[LUAHIREDIS_MAXARGS];
  int nargs = load_args(L, pContext, 2, argv, argvlen);

  int nret = 0;

  redisReply * pReply = (redisReply *)redisCommandArgv(
      pContext, nargs, argv, argvlen
    );
  if (pReply == NULL)
  {
    /* TODO: Shouldn't we clear the context error state somehow after this? */
    return push_error(L, pContext);
  }

  nret = push_reply(L, pReply);

  /*
  * TODO: Not entirely safe: if above code throws error, reply object is leaked.
  */
  freeReplyObject(pReply);
  pReply = NULL;

  return nret;
}
Esempio n. 4
0
static int lconn_get_reply(lua_State * L)
{
  redisContext * pContext = check_connection(L, 1);
  /* int base = lua_gettop(L); */

  int nret = 0;

  redisReply * pReply = NULL;

  int ok = redisGetReply(pContext, (void **)&pReply);
  if (ok != REDIS_OK || pReply == NULL)
  {
    /* TODO: Shouldn't we clear the context error state somehow after this? */
    return push_error(L, pContext);
  }

  /*
  if (lua_gettop(L) != base)
  {
    freeReplyObject(pReply);
    return luaL_error(
        L, "lhrstackerror1 actual %d expected %d", lua_gettop(L), base
      );
  }
  */

  nret = push_reply(L, pReply);

  /*
  if (lua_gettop(L) != base + nret)
  {
    freeReplyObject(pReply);
    return luaL_error(
        L, "lhrstackerror2 actual %d expected %d base %d", lua_gettop(L),
        base + nret, base
      );
  }
  */

  /*
  * TODO: Not entirely safe: if above code throws error, reply object is leaked.
  */
  freeReplyObject(pReply);
  pReply = NULL;

  return nret;
}
Esempio n. 5
0
static int push_reply(lua_State *L, redisReply *redisReply)
{
  switch(redisReply->type)
  {
    case REDIS_REPLY_ERROR:
      luv_push_async_error_raw(L, NULL, redisReply->str, "push_reply", NULL);
      break;

    case REDIS_REPLY_STATUS:
      lua_pushlstring(L, redisReply->str, redisReply->len);
      break;

    case REDIS_REPLY_INTEGER:
      lua_pushinteger(L, redisReply->integer);
      break;

    case REDIS_REPLY_NIL:
      lua_pushnil(L);
      break;

    case REDIS_REPLY_STRING:
      lua_pushlstring(L, redisReply->str, redisReply->len);
      break;

    case REDIS_REPLY_ARRAY:
    {
      unsigned int i;
      lua_createtable(L, redisReply->elements, 0);

      for (i = 0; i < redisReply->elements; ++i)
      {
        push_reply(L, redisReply->element[i]);
        lua_rawseti(L, -2, i + 1); /* Store sub-reply */
      }

      break;
    }

    default:
      return luaL_error(L, "Unknown reply type: %d", redisReply->type);
  }

  return 1;
}
Esempio n. 6
0
bool parse_redis_protocol(struct request *req)
{
	int         ret;
	void        *reply;    
	redisReader *reader;   
	
	if(strncmp(req->buf, "$-1", 3) == 0)
	{
		lua_pushboolean(req->vm, false);
		return true;
	}
	else if(strncmp(req->buf, "+OK", 3) == 0)
	{
		lua_pushboolean(req->vm, true);
		return true;
	}
	
	reader = redisReaderCreate();
	
	DEBUG_PRINT("req->buf=%s\r\n", req->buf);
	redisReaderFeed(reader, req->buf, sdslen(req->buf));
	ret = redisReaderGetReply(reader,&reply);
	
	if (ret == REDIS_ERR) 
	{
		freeReplyObject(reply);    
		redisReaderFree(reader);
		return false;
	}
	
	
	push_reply(req->vm, (redisReply*)reply);
	
	//printf("%s\r\n", ((redisReply*)reply)->str);
	freeReplyObject(reply);    
	redisReaderFree(reader);
	
	return true;
}
Esempio n. 7
0
static int push_reply(lua_State * L, redisReply * pReply)
{
  switch (pReply->type)
  {
    case REDIS_REPLY_STATUS:
      luaL_checkstack(L, 2, "not enough stack to push reply");

      lua_pushvalue(L, lua_upvalueindex(1)); /* M (module table) */
      lua_getfield(L, -1, "status"); /* status = M.status */
      lua_remove(L, -2); /* Remove module table from stack */

      lua_pushlstring(L, pReply->str, pReply->len); /* name */
      lua_gettable(L, -2); /* status[name] */

      lua_remove(L, -2); /* Remove status table from stack */

      break;

    case REDIS_REPLY_ERROR:
      /* Not caching errors, they are (hopefully) not that common */
      push_new_const(L, pReply->str, pReply->len, REDIS_REPLY_ERROR);
      break;

    case REDIS_REPLY_INTEGER:
      luaL_checkstack(L, 1, "not enough stack to push reply");
      lua_pushinteger(L, pReply->integer);
      break;

    case REDIS_REPLY_NIL:
      luaL_checkstack(L, 2, "not enough stack to push reply");
      lua_pushvalue(L, lua_upvalueindex(1)); /* module table */
      lua_getfield(L, -1, LUAHIREDIS_KEY_NIL);
      lua_remove(L, -2); /* module table */
      break;

    case REDIS_REPLY_STRING:
      luaL_checkstack(L, 1, "not enough stack to push reply");
      lua_pushlstring(L, pReply->str, pReply->len);
      break;

    case REDIS_REPLY_ARRAY:
    {
      unsigned int i = 0;

      luaL_checkstack(L, 2, "not enough stack to push reply");

      lua_createtable(L, pReply->elements, 0);

      for (i = 0; i < pReply->elements; ++i)
      {
        /*
        * Not controlling recursion depth:
        * if we parsed the reply somehow,
        * we hope to be able to push it.
        */

        push_reply(L, pReply->element[i]);
        lua_rawseti(L, -2, i + 1); /* Store sub-reply */
      }

      break;
    }

    default: /* should not happen */
      return luaL_error(L, "command: unknown reply type: %d", pReply->type);
  }

  /*
  * Always returning a single value.
  * If changed, change REDIS_REPLY_ARRAY above.
  */
  return 1;
}
Esempio n. 8
0
static int push_reply(lua_State * L, redisReply * pReply)
{
  /* int base = lua_gettop(L); */

  switch(pReply->type)
  {
    case REDIS_REPLY_STATUS:
      lua_pushvalue(L, lua_upvalueindex(1)); /* M (module table) */

      lua_pushlstring(L, pReply->str, pReply->len); /* status */
      lua_gettable(L, -2); /* M[status] */

      if (lua_isnil(L, -1)) /* Not bothering with metatables */
      {
        /*
        * TODO: Following code is likely to be broken due to early binding
        * (imagine that RETURN is a command that returns given string
        * as a status):
        *
        *    assert(conn:command("RETURN", "FOO") == hiredis.FOO)
        *
        * Here hiredis.FOO would be nil before conn:command() is called.
        *
        * Note that this is not relevant to the current Redis implementation
        * (that is 2.2 and before), since it seems that it wouldn't
        * return any status code except OK, QUEUED or PONG,
        * all of which are alread covered.
        */
        lua_pushlstring(L, pReply->str, pReply->len); /* status */
        push_new_const(
            L, pReply->str, pReply->len, REDIS_REPLY_STATUS /* const */
          );
        lua_settable(L, -3); /* M[status] = const */

        lua_pushlstring(L, pReply->str, pReply->len); /* status */
        lua_gettable(L, -2); /* return M[status] */
      }

      lua_remove(L, -2); /* Remove module table */

      break;

    case REDIS_REPLY_ERROR:
      /* Not caching errors, they are (hopefully) not that common */
      push_new_const(L, pReply->str, pReply->len, REDIS_REPLY_ERROR);
      break;

    case REDIS_REPLY_INTEGER:
      lua_pushinteger(L, pReply->integer);
      break;

    case REDIS_REPLY_NIL:
      lua_pushvalue(L, lua_upvalueindex(1)); /* module table */
      lua_getfield(L, -1, LUAHIREDIS_KEY_NIL);
      lua_remove(L, -2); /* module table */
      break;

    case REDIS_REPLY_STRING:
      lua_pushlstring(L, pReply->str, pReply->len);
      break;

    case REDIS_REPLY_ARRAY:
    {
      unsigned int i = 0;

      lua_createtable(L, pReply->elements, 0);

      for (i = 0; i < pReply->elements; ++i)
      {
        /*
        * Not controlling recursion depth:
        * if we parsed the reply somehow,
        * we hope to be able to push it.
        */

        push_reply(L, pReply->element[i]);
        lua_rawseti(L, -2, i + 1); /* Store sub-reply */
      }
      break;
    }

    default: /* should not happen */
      return luaL_error(L, "command: unknown reply type: %d", pReply->type);
  }

  /*
  if (lua_gettop(L) != base + 1)
  {
    return luaL_error(L, "pushreplystackerror: actual %d expected %d base %d type %d", lua_gettop(L), base + 1, base, pReply->type);
  }
  */

  /*
  * Always returning a single value.
  * If changed, change REDIS_REPLY_ARRAY above.
  */
  return 1;
}