> OT, but will you contribute that to mod_lua ? :) Based on mod_memcache and mod_wombat . For demonstration only as this uses our hacked version, but you get the idea how simple this was. Build it in lua dir like /usr/lib/lua/5.1/apach2/memcache.so
-- Brian Akins Chief Operations Engineer Turner Digital Media Technologies
#include "mod_memcache.h" #include "mod_lua_request.h" typedef struct { apr_memcache_t *memcache; request_rec *request; } lua_memcache_t; static lua_memcache_t *check_memcache(lua_State * L, int index) { lua_memcache_t *lm; luaL_checkudata(L, index, "Apache2.Memcache"); lm = (lua_memcache_t *) lua_unboxpointer(L, index); return lm; } static int get_client(lua_State * L) { lua_memcache_t *lm; apr_memcache_t *m; request_rec *r = lr_check_request_rec(L, 1); m = ap_memcache_client(r->server); lm = apr_pcalloc(r->pool, sizeof(lua_memcache_t)); lm->memcache = m; lm->request = r; lua_boxpointer(L, lm); luaL_getmetatable(L, "Apache2.Memcache"); lua_setmetatable(L, -2); return 1; } /*these are fairly repetitive. can we combine this and not be slow?*/ /*only returns data for now and assumes it's a string*/ static int get_value(lua_State * L) { lua_memcache_t *lm = check_memcache(L, 1); apr_memcache_t *m = lm->memcache; request_rec *r = lm->request; const char *key = luaL_checkstring(L, 2); char *data = NULL; apr_size_t len; apr_status_t rv; apr_uint16_t flags; rv = apr_memcache_getp(m, r->pool, key, &data, &len, &flags); if(APR_SUCCESS != rv || NULL == data) { lua_pushnil(L); } else { lua_pushstring(L, data); } return 1; } /*only returns data for now and assumes it's a string*/ static int set_value(lua_State * L) { lua_memcache_t *lm = check_memcache(L, 1); apr_memcache_t *m = lm->memcache; request_rec *r = lm->request; const char *key = luaL_checkstring(L, 2); char *data = (char *)luaL_checkstring(L, 3); apr_uint32_t timeout = luaL_checkint(L, 4); apr_size_t len; apr_status_t rv; apr_uint16_t flags = 0; /*do we have to make a copy??*/ data = apr_pstrdup(r->pool, data); len = strlen(data); rv = apr_memcache_set(m, key, data, len, timeout, flags); /*how to handle errors?*/ return 0; } static int incr_value(lua_State * L) { lua_memcache_t *lm = check_memcache(L, 1); apr_memcache_t *m = lm->memcache; request_rec *r = lm->request; const char *key = luaL_checkstring(L, 2); int n = 1; int nv = 0; int top = lua_gettop(L); apr_status_t rv; /*default to one, but if user gives another argument, use it*/ if(top > 2) { n = luaL_checknumber(L, 3); } rv = apr_memcache_incr(m, key, n, &nv); /*XXX: need to deal with errors. what if rv != APR_SUCCESS*/ lua_pushnumber(L, nv); return 1; } static int decr_value(lua_State * L) { lua_memcache_t *lm = check_memcache(L, 1); apr_memcache_t *m = lm->memcache; request_rec *r = lm->request; const char *key = luaL_checkstring(L, 2); int n = 1; int nv = 0; int top = lua_gettop(L); apr_status_t rv; /*default to one, but if user gives another argument, use it*/ if(top > 2) { n = luaL_checknumber(L, 3); } rv = apr_memcache_decr(m, key, n, &nv); /*XXX: need to deal with errors. what if rv != APR_SUCCESS*/ lua_pushnumber(L, nv); return 1; } static const struct luaL_Reg memcache_funcs[] = { {"client", get_client}, {NULL, NULL} }; static const struct luaL_Reg memcache_methods[] = { {"get", get_value}, {"set", set_value}, {"incr", incr_value}, {"decr", decr_value}, {NULL, NULL} }; int luaopen_apache2_memcache(lua_State * L) { luaL_newmetatable(L, "Apache2.Memcache"); lua_pushvalue(L, -1); lua_setfield(L, -2, "__index"); luaL_register(L, NULL, memcache_methods); luaL_register(L, "memcache", memcache_funcs); return 1; }