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

Reply via email to