> 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;
}