Repository: trafficserver
Updated Branches:
  refs/heads/master b6680179a -> d30401990


TS-4129: Support TSContSchedule in ts_lua plugin. This closes #420


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/d3040199
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/d3040199
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/d3040199

Branch: refs/heads/master
Commit: d30401990ada424cb0b6acbcb4cfeab31bdb979f
Parents: b668017
Author: Kit Chan <[email protected]>
Authored: Wed Jan 20 23:26:42 2016 -0800
Committer: Kit Chan <[email protected]>
Committed: Wed Jan 20 23:26:42 2016 -0800

----------------------------------------------------------------------
 doc/admin-guide/plugins/ts_lua.en.rst           |  30 +++++
 .../ts_lua/example/test_schedule.lua            |  48 +++++++
 plugins/experimental/ts_lua/ts_lua_misc.c       | 124 +++++++++++++++++++
 plugins/experimental/ts_lua/ts_lua_util.c       |  41 ++++++
 plugins/experimental/ts_lua/ts_lua_util.h       |   3 +
 5 files changed, 246 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/d3040199/doc/admin-guide/plugins/ts_lua.en.rst
----------------------------------------------------------------------
diff --git a/doc/admin-guide/plugins/ts_lua.en.rst 
b/doc/admin-guide/plugins/ts_lua.en.rst
index 66de2d9..2cc8dc2 100644
--- a/doc/admin-guide/plugins/ts_lua.en.rst
+++ b/doc/admin-guide/plugins/ts_lua.en.rst
@@ -2379,6 +2379,36 @@ Here is an example:
 
 `TOP <#ts-lua-plugin>`_
 
+ts.schedule
+-----------
+**syntax:** *ts.schedule(THREAD_TYPE, sec, FUNCTION, param1?, param2?, ...)*
+
+**context:** *after do_remap*
+
+**description:** Schedule function to be run after specified seconds without 
blocking.
+
+Behind the scene, this method makes use of the ATS event model.
+
+Here is an example:
+
+::
+
+    function schedule()
+        ts.debug('test schedule starts')
+    end
+
+    function cache_lookup()
+        ts.debug('cache-lookup')
+        ts.schedule(TS_LUA_THREAD_POOL_NET, 0, schedule)
+        return 0
+    end
+
+    function do_remap()
+        ts.hook(TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE, cache_lookup)
+    end
+
+`TOP <#ts-lua-plugin>`_
+
 ts.http.config_int_get
 ----------------------
 **syntax:** *val = ts.http.config_int_get(CONFIG)*

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/d3040199/plugins/experimental/ts_lua/example/test_schedule.lua
----------------------------------------------------------------------
diff --git a/plugins/experimental/ts_lua/example/test_schedule.lua 
b/plugins/experimental/ts_lua/example/test_schedule.lua
new file mode 100644
index 0000000..d80e843
--- /dev/null
+++ b/plugins/experimental/ts_lua/example/test_schedule.lua
@@ -0,0 +1,48 @@
+--  Licensed to the Apache Software Foundation (ASF) under one
+--  or more contributor license agreements.  See the NOTICE file
+--  distributed with this work for additional information
+--  regarding copyright ownership.  The ASF licenses this file
+--  to you under the Apache License, Version 2.0 (the
+--  "License"); you may not use this file except in compliance
+--  with the License.  You may obtain a copy of the License at
+--
+--  http://www.apache.org/licenses/LICENSE-2.0
+--
+--  Unless required by applicable law or agreed to in writing, software
+--  distributed under the License is distributed on an "AS IS" BASIS,
+--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+--  See the License for the specific language governing permissions and
+--  limitations under the License.
+
+
+function schedule()
+    ts.debug('test schedule starts')
+
+    -- test.com needs to be handled by ATS in remap.config
+    local url = 'http://test.com/test.php'
+    local res = ts.fetch(url)
+    ts.debug('test fetch')
+    if res.status == 200 then
+        local b = res.body
+        local len = string.len(b)
+        ts.debug(len)
+    end
+    ts.debug('test schedule ends')
+end
+
+function cache_lookup()
+  ts.debug('cache-lookup')
+  ts.schedule(TS_LUA_THREAD_POOL_NET, 0, schedule)
+  return 0
+end
+
+function do_global_read_request()
+    local inner = ts.http.is_internal_request()
+    if inner ~= 0 then
+        ts.debug('internal')
+        return 0
+    end
+
+    ts.hook(TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE, cache_lookup)
+    return 0
+end

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/d3040199/plugins/experimental/ts_lua/ts_lua_misc.c
----------------------------------------------------------------------
diff --git a/plugins/experimental/ts_lua/ts_lua_misc.c 
b/plugins/experimental/ts_lua/ts_lua_misc.c
index 5fc5b00..e9f8223 100644
--- a/plugins/experimental/ts_lua/ts_lua_misc.c
+++ b/plugins/experimental/ts_lua/ts_lua_misc.c
@@ -24,9 +24,13 @@ static int ts_lua_get_now_time(lua_State *L);
 static int ts_lua_debug(lua_State *L);
 static int ts_lua_error(lua_State *L);
 static int ts_lua_sleep(lua_State *L);
+static int ts_lua_schedule(lua_State *L);
 
 static int ts_lua_sleep_cleanup(ts_lua_async_item *ai);
 static int ts_lua_sleep_handler(TSCont contp, TSEvent event, void *edata);
+static int ts_lua_schedule_handler(TSCont contp, TSEvent event, void *edata);
+
+static void ts_lua_inject_misc_variables(lua_State *L);
 
 void
 ts_lua_inject_misc_api(lua_State *L)
@@ -46,6 +50,21 @@ ts_lua_inject_misc_api(lua_State *L)
   /* ts.sleep(...) */
   lua_pushcfunction(L, ts_lua_sleep);
   lua_setfield(L, -2, "sleep");
+
+  /* ts.schedule(...) */
+  lua_pushcfunction(L, ts_lua_schedule);
+  lua_setfield(L, -2, "schedule");
+
+  ts_lua_inject_misc_variables(L);
+}
+
+static void
+ts_lua_inject_misc_variables(lua_State *L)
+{
+  lua_pushinteger(L, TS_THREAD_POOL_NET);
+  lua_setglobal(L, "TS_LUA_THREAD_POOL_NET");
+  lua_pushinteger(L, TS_THREAD_POOL_TASK);
+  lua_setglobal(L, "TS_LUA_THREAD_POOL_TASK");
 }
 
 static int
@@ -82,6 +101,111 @@ ts_lua_error(lua_State *L)
 }
 
 static int
+ts_lua_schedule(lua_State *L)
+{
+  int sec;
+  int type;
+  int entry;
+
+  ts_lua_http_ctx *actx;
+
+  int n;
+
+  TSCont contp;
+  ts_lua_cont_info *ci;
+  ts_lua_cont_info *nci;
+
+  ci = ts_lua_get_cont_info(L);
+  if (ci == NULL)
+    return 0;
+
+  entry = lua_tointeger(L, 1);
+
+  sec = luaL_checknumber(L, 2);
+  if (sec < 1) {
+    sec = 0;
+  }
+
+  type = lua_type(L, 3);
+  if (type != LUA_TFUNCTION)
+    return 0;
+
+  n = lua_gettop(L);
+
+  if (n < 3) {
+    TSError("[ts_lua] ts.http.schedule need at least three params");
+    return 0;
+  }
+
+  // TO-DO unset the original context in L
+  actx = ts_lua_create_async_ctx(L, ci, n);
+
+  contp = TSContCreate(ts_lua_schedule_handler, ci->mutex);
+  TSContDataSet(contp, actx);
+
+  nci = &actx->cinfo;
+  nci->contp = contp;
+  nci->mutex = ci->mutex;
+
+  TSContSchedule(contp, sec * 1000, entry);
+
+  return 0;
+}
+
+static int
+ts_lua_schedule_handler(TSCont contp, TSEvent ev, void *edata)
+{
+  lua_State *L;
+  ts_lua_cont_info *ci;
+  ts_lua_coroutine *crt;
+  int event, n, ret, rc;
+  ts_lua_http_ctx *actx;
+  ts_lua_main_ctx *main_ctx;
+
+  event = (int)ev;
+  TSDebug(TS_LUA_DEBUG_TAG, "getting actx and other info");
+  actx = (ts_lua_http_ctx *)TSContDataGet(contp);
+
+  TSDebug(TS_LUA_DEBUG_TAG, "getting http_Ctx");
+  ci = &actx->cinfo;
+  crt = &ci->routine;
+
+  main_ctx = crt->mctx;
+  L = crt->lua;
+
+  rc = ret = 0;
+
+  TSMutexLock(main_ctx->mutexp);
+  ts_lua_set_cont_info(L, ci);
+
+  if (event == TS_LUA_EVENT_COROUTINE_CONT) {
+    TSDebug(TS_LUA_DEBUG_TAG, "event is coroutine_cont");
+    n = (intptr_t)edata;
+    ret = lua_resume(L, n);
+  } else {
+    TSDebug(TS_LUA_DEBUG_TAG, "event is not coroutine_cont");
+    n = lua_gettop(L);
+    ret = lua_resume(L, n - 1);
+  }
+
+  if (ret == LUA_YIELD) {
+    TSMutexUnlock(main_ctx->mutexp);
+    goto done;
+  }
+
+  if (ret != 0) {
+    TSError("[ts_lua] lua_resume failed: %s", lua_tostring(L, -1));
+  }
+
+  lua_pop(L, lua_gettop(L));
+  TSMutexUnlock(main_ctx->mutexp);
+  ts_lua_destroy_async_ctx(actx);
+
+done:
+  return 0;
+}
+
+static int
 ts_lua_sleep(lua_State *L)
 {
   int sec;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/d3040199/plugins/experimental/ts_lua/ts_lua_util.c
----------------------------------------------------------------------
diff --git a/plugins/experimental/ts_lua/ts_lua_util.c 
b/plugins/experimental/ts_lua/ts_lua_util.c
index ddef163..19e0bac 100644
--- a/plugins/experimental/ts_lua/ts_lua_util.c
+++ b/plugins/experimental/ts_lua/ts_lua_util.c
@@ -338,6 +338,47 @@ ts_lua_get_cont_info(lua_State *L)
   return ci;
 }
 
+ts_lua_http_ctx *
+ts_lua_create_async_ctx(lua_State *L, ts_lua_cont_info *hci, int n)
+{
+  int i;
+  lua_State *l;
+  ts_lua_coroutine *crt;
+  ts_lua_http_ctx *actx;
+
+  actx = TSmalloc(sizeof(ts_lua_http_ctx));
+  memset(actx, 0, sizeof(ts_lua_http_ctx));
+
+  // create lua_thread
+  l = lua_newthread(L);
+
+  // init the coroutine
+  crt = &actx->cinfo.routine;
+  crt->mctx = hci->routine.mctx;
+  crt->lua = l;
+  crt->ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+  // replace the param; start with 2 because first two params are not needed
+  for (i = 2; i < n; i++) {
+    lua_pushvalue(L, i + 1);
+  }
+
+  lua_xmove(L, l, n - 2);
+
+  return actx;
+}
+
+void
+ts_lua_destroy_async_ctx(ts_lua_http_ctx *http_ctx)
+{
+  ts_lua_cont_info *ci;
+
+  ci = &http_ctx->cinfo;
+
+  ts_lua_release_cont_info(ci);
+  TSfree(http_ctx);
+}
+
 void
 ts_lua_set_http_ctx(lua_State *L, ts_lua_http_ctx *ctx)
 {

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/d3040199/plugins/experimental/ts_lua/ts_lua_util.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ts_lua/ts_lua_util.h 
b/plugins/experimental/ts_lua/ts_lua_util.h
index 7cd7675..e3dc9a9 100644
--- a/plugins/experimental/ts_lua/ts_lua_util.h
+++ b/plugins/experimental/ts_lua/ts_lua_util.h
@@ -39,6 +39,9 @@ ts_lua_instance_conf *ts_lua_get_instance_conf(lua_State *L);
 void ts_lua_set_cont_info(lua_State *L, ts_lua_cont_info *ci);
 ts_lua_cont_info *ts_lua_get_cont_info(lua_State *L);
 
+ts_lua_http_ctx *ts_lua_create_async_ctx(lua_State *L, ts_lua_cont_info *hci, 
int n);
+void ts_lua_destroy_async_ctx(ts_lua_http_ctx *http_ctx);
+
 void ts_lua_set_http_ctx(lua_State *L, ts_lua_http_ctx *ctx);
 ts_lua_http_ctx *ts_lua_get_http_ctx(lua_State *L);
 

Reply via email to