static int
ngx_http_lua_ngx_co(lua_State *L)
{
ngx_http_request_t *r;
ngx_http_lua_ctx_t *ctx;
ngx_http_lua_co_ctx_t *coctx;
ngx_http_lua_wakeup_co_t *wakeup_co;
r = ngx_http_lua_get_req(L);
if (r == NULL) {
return luaL_error(L, "no request found");
}
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
if (ctx == NULL) {
return luaL_error(L, "no request ctx found");
}
ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
| NGX_HTTP_LUA_CONTEXT_ACCESS
| NGX_HTTP_LUA_CONTEXT_CONTENT
| NGX_HTTP_LUA_CONTEXT_TIMER);
coctx = ctx->cur_co_ctx;
if (coctx == NULL) {
return luaL_error(L, "no co ctx found");
}
lua_pushlightuserdata(L, &ngx_http_lua_wakeup_co_key);
lua_rawget(L, LUA_REGISTRYINDEX);
wakeup_co = coctx->wakeup_co;
if (wakeup_co == NULL) {
wakeup_co = (ngx_http_lua_wakeup_co_t *)
lua_newuserdata(L, sizeof(ngx_http_lua_wakeup_co_t));
if (wakeup_co == NULL) {
return luaL_error(L, "no memory");
}
wakeup_co->co_ctx = NULL;
wakeup_co->self_ref = luaL_ref(L, -2);
coctx->wakeup_co = wakeup_co;
}
lua_rawgeti(L, -1, wakeup_co->self_ref);
return 1;
}
static int
ngx_http_lua_ngx_sleep(lua_State *L)
{
int n;
ngx_int_t delay; /* in msec */
ngx_http_request_t *r;
ngx_http_lua_ctx_t *ctx;
ngx_http_lua_co_ctx_t *coctx;
r = ngx_http_lua_get_req(L);
if (r == NULL) {
return luaL_error(L, "no request found");
}
n = lua_gettop(L);
if ( n == 1 ) {
delay = (ngx_int_t) (luaL_checknumber(L, 1) * 1000);
if (delay < 0) {
delay = -1;
}
} else if ( n == 0 ) {
delay = -1;
} else {
return luaL_error(L, "attempt to pass %d arguments, but accepted 1",
n);
}
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
if (ctx == NULL) {
return luaL_error(L, "no request ctx found");
}
ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
| NGX_HTTP_LUA_CONTEXT_ACCESS
| NGX_HTTP_LUA_CONTEXT_CONTENT
| NGX_HTTP_LUA_CONTEXT_TIMER);
coctx = ctx->cur_co_ctx;
if (coctx == NULL) {
return luaL_error(L, "no co ctx found");
}
ngx_http_lua_cleanup_pending_operation(coctx);
coctx->cleanup = ngx_http_lua_sleep_cleanup;
coctx->data = r;
if ( delay >= 0 ) {
coctx->sleep.handler = ngx_http_lua_sleep_handler;
coctx->sleep.data = coctx;
coctx->sleep.log = r->connection->log;
dd("adding timer with delay %lu ms, r:%.*s", (unsigned long) delay,
(int) r->uri.len, r->uri.data);
ngx_add_timer(&coctx->sleep, (ngx_msec_t) delay);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"lua ready to sleep for %d ms", delay);
}
if ( coctx->wakeup_co != NULL ) {
coctx->wakeup_co->co_ctx = coctx;
}
return lua_yield(L, 0);
}
static int
ngx_http_lua_ngx_wakeup(lua_State *L)
{
int n;
ngx_int_t rc;
ngx_connection_t *c;
ngx_http_request_t *r;
ngx_http_log_ctx_t *log_ctx;
ngx_http_lua_ctx_t *ctx;
ngx_http_lua_co_ctx_t *coctx;
ngx_http_lua_wakeup_co_t *wakeup_co;
r = ngx_http_lua_get_req(L);
if (r == NULL) {
return luaL_error(L, "no request found");
}
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
if (ctx == NULL) {
return luaL_error(L, "no request ctx found");
}
ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
| NGX_HTTP_LUA_CONTEXT_ACCESS
| NGX_HTTP_LUA_CONTEXT_CONTENT
| NGX_HTTP_LUA_CONTEXT_TIMER);
n = lua_gettop(L);
if (n == 0) {
return luaL_error(L, "pass 0 arguments, but accepted 1");
}
wakeup_co = (ngx_http_lua_wakeup_co_t*) lua_touserdata(L, 1);
if (wakeup_co == NULL) {
return luaL_error(L, "argument 1 only accept value returned by co()");
}
coctx = wakeup_co->co_ctx;
if (coctx == NULL) {
lua_pushboolean(L, 0);
return 1;
}
coctx->cleanup = NULL;
wakeup_co->co_ctx = NULL;
if (coctx->sleep.timer_set) {
ngx_del_timer(&coctx->sleep);
}
r = coctx->data;
c = r->connection;
if (c->fd != -1) { /* not a fake connection */
log_ctx = c->log->data;
log_ctx->current_request = r;
}
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
if (ctx == NULL) {
lua_pushboolean(L, 0);
return 1;
}
ctx->cur_co_ctx = coctx;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
"lua sleep wakeuped: \"%V?%V\"", &r->uri, &r->args);
if (--n > 0) {
lua_xmove(L, coctx->co, n);
}
rc = ngx_http_lua_run_thread(L, r, ctx, n);
lua_pushboolean(L, 1);
return 1;
}