Changeset 452

Show
Ignore:
Timestamp:
07/15/2005 05:46:13 PM (3 years ago)
Author:
jan
Message:

ported mod_cml to lua

Location:
branches/lighttpd-1.3.x
Files:
6 modified

Legend:

Unmodified
Added
Removed
  • branches/lighttpd-1.3.x/configure.in

    r436 r452  
    272272],[AC_MSG_RESULT(no)]) 
    273273AC_SUBST(MEMCACHE_LIB) 
    274           
     274 
     275AC_MSG_CHECKING(for lua) 
     276AC_ARG_WITH(lua, AC_HELP_STRING([--with-lua],[lua engine for mod_cml]), 
     277[AC_MSG_RESULT(yes) 
     278 AC_CHECK_LIB(lua, lua_open, [ 
     279         AC_CHECK_HEADERS([lua.h],[ 
     280                 LUA_LIB="-llua -llualib -lm" 
     281                 AC_DEFINE([HAVE_LUA], [1], [liblua]) 
     282                 AC_DEFINE([HAVE_LUA_H], [1]) 
     283         ]) 
     284 ]) 
     285],[AC_MSG_RESULT(no)]) 
     286AC_SUBST(LUA_LIB) 
     287 
    275288 
    276289AC_SEARCH_LIBS(socket,socket) 
  • branches/lighttpd-1.3.x/doc/cml.txt

    r427 r452  
    1212 
    1313:abstract: 
    14   CML is a Meta language to describe the dependencies of a page at one side and building a page from its fragments on the other side 
     14  CML is a Meta language to describe the dependencies of a page at one side and building a page from its fragments on the other side using LUA. 
    1515   
    1616.. meta:: 
    17   :keywords: lighttpd, cml 
     17  :keywords: lighttpd, cml, lua 
    1818   
    1919.. contents:: Table of Contents 
     
    9898and the following index.cml file: :: 
    9999 
    100   output.content-type text/html 
    101  
    102   output.include _cache.html 
    103  
    104   trigger.handler index.php 
    105   trigger.if  file.mtime("../lib/php/menu.csv") > file.mtime("_cache.html") 
    106   trigger.if  file.mtime("templates/jk.tmpl") > file.mtime("_cache.html") 
    107   trigger.if  file.mtime("content.html") > file.mtime("_cache.html") 
     100  output_contenttype = "text/html" 
     101 
     102  b = request["DOCUMENT_ROOT"] 
     103  cwd = request["CWD"] 
     104 
     105  output_include = { b + "_cache.html" } 
     106 
     107  trigger_handler = "index.php" 
     108 
     109  if file_mtime(b + "../lib/php/menu.csv") > file_mtime(cwd + "_cache.html") or 
     110     file_mtime(b + "templates/jk.tmpl")   > file.mtime(cwd + "_cache.html") 
     111     file.mtime(b + "content.html")        > file.mtime(cwd + "_cache.html") then 
     112     return 1 
     113  else  
     114     return 0 
     115  end 
    108116 
    109117Numbers again: 
     
    133141The index.cml for this looks like: :: 
    134142 
    135   output.content-type text/html 
     143  output_content_type = "text/html" 
     144   
     145  cwd = request["CWD"] 
    136146    
    137   output.include head.html 
    138   output.include menu.html 
    139   output.include spacer.html 
    140   output.include db-content.html 
    141   output.include spacer2.html 
    142   output.include news.html 
    143   output.include footer.html 
     147  output_include = { cwd + "head.html",  
     148                     cwd + "menu.html", 
     149                     cwd + "spacer.html", 
     150                     cwd + "db-content.html", 
     151                     cwd + "spacer2.html", 
     152                     cwd + "news.html", 
     153                     cwd + "footer.html" } 
     154   
     155  return 0 
    144156 
    145157Now we get about 10000 req/s instead of 600 req/s. 
     
    150162:cml.extension:  
    151163  the file extension that is bound to the cml-module 
     164:cml.memcache-hosts: 
     165  hosts for the memcache.* functions 
     166:cml.memcache-namespace: 
     167  (not used yet) 
    152168 
    153169Language 
    154170======== 
    155171 
    156 ... will come later ...  
     172The language used for CML is provided by `LUA <http://www.lua.org/>`_.  
     173 
     174Additionally to the functions provided by lua mod_cml provides: :: 
     175 
     176  tables: 
     177 
     178  request 
     179    - REQUEST_URI 
     180    - SCRIPT_NAME 
     181    - SCRIPT_FILENAME 
     182    - DOCUMENT_ROOT 
     183    - PATH_INFO 
     184    - CWD 
     185    - BASEURI 
     186 
     187  get 
     188    - parameters from the query-string 
     189 
     190  functions: 
     191  string md5(string) 
     192  number file_mtime(string) 
     193  string memcache_get_string(string) 
     194  number memcache_get_long(string) 
     195  boolean memcache_exists(string)  
     196 
     197 
     198What ever your script does, it has to return either 0 or 1 for ``cache-hit`` or ``cache-miss``.  
     199It case a error occures check the error-log, the user will get a error 500. If you don't like  
     200the standard error-page use ``server.errorfile-prefix``. 
     201 
     202Examples 
     203======== 
     204 
     205Using the memcache-udf for MySQL we can do: :: 
     206 
     207  output_contenttype = "text/html" 
     208  output_include = { "cache-hit.html" } 
     209 
     210  trigger_handler = "generate.php" 
     211 
     212  if get["page"] == memcache_get_string("123") then 
     213    return 0 
     214  else 
     215    return 1 
     216  end 
     217 
     218In MySQL you do: :: 
     219 
     220  SELECT memcache_set("127.0.0.1:11211", "123", "12"); 
     221 
     222or to retrieve a value: 
     223 
     224   SELECT memcache_get("127.0.0.1:11211", "123"); 
     225 
     226You can get the mysql udf at `jan's mysql page <http://jan.kneschke.de/projects/mysql/udf/>`_. 
  • branches/lighttpd-1.3.x/src/Makefile.am

    r432 r452  
    7070 
    7171lib_LTLIBRARIES += mod_cml.la 
    72 mod_cml_la_SOURCES = mod_cml.c mod_cml_funcs.c mod_cml_logic.c 
     72mod_cml_la_SOURCES = mod_cml.c mod_cml_lua.c mod_cml_funcs.c 
    7373mod_cml_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined 
    74 mod_cml_la_LIBADD = $(MEMCACHE_LIB) $(common_libadd) 
     74mod_cml_la_LIBADD = $(MEMCACHE_LIB) $(common_libadd) $(LUA_LIB) 
    7575 
    7676lib_LTLIBRARIES += mod_trigger_b4_dl.la 
  • branches/lighttpd-1.3.x/src/mod_cml.c

    r440 r452  
    2929        p->trigger_handler = buffer_init(); 
    3030         
    31         p->eval            = buffer_array_init(); 
    32         p->trigger_if      = buffer_array_init(); 
    33         p->output_include  = buffer_array_init(); 
    34         p->params          = tnode_val_array_init(); 
    35          
    3631        return p; 
    3732} 
     
    6358                free(p->config_storage); 
    6459        } 
    65          
    66         tnode_val_array_free(p->params); 
    67          
    68         buffer_array_free(p->eval); 
    69         buffer_array_free(p->trigger_if); 
    70         buffer_array_free(p->output_include); 
    7160         
    7261        buffer_free(p->trigger_handler); 
     
    10493                s->mc_hosts       = array_init(); 
    10594                s->mc_namespace   = buffer_init(); 
     95#if defined(HAVE_MEMCACHE_H) 
     96                s->mc = NULL; 
     97#endif 
    10698                 
    10799                cv[0].destination = s->ext; 
     
    323315        plugin_data *p = p_d; 
    324316        size_t i; 
     317        int ret; 
    325318         
    326319        if (fn->used == 0) return HANDLER_ERROR; 
     
    332325                mod_cml_patch_connection(srv, con, p, CONST_BUF_LEN(patch)); 
    333326        } 
    334          
    335         buffer_array_reset(p->output_include); 
    336         buffer_array_reset(p->eval); 
    337         buffer_array_reset(p->trigger_if); 
    338327         
    339328        buffer_reset(p->basedir); 
     
    341330        buffer_reset(p->session_id); 
    342331        buffer_reset(p->trigger_handler); 
    343          
    344         tnode_val_array_reset(p->params); 
    345332         
    346333        if (buffer_is_empty(p->conf.ext)) return HANDLER_GO_ON; 
     
    383370        cache_get_session_id(srv, con, p); 
    384371         
    385         switch(cache_parse(srv, con, p, fn)) { 
     372        ret = cache_parse_lua(srv, con, p, fn); 
     373         
     374        switch(ret) { 
    386375        case -1: 
    387376                /* error */ 
  • branches/lighttpd-1.3.x/src/mod_cml.h

    r441 r452  
    77 
    88#include "stream.h" 
     9#include "plugin.h" 
    910 
    1011#if defined(HAVE_MEMCACHE_H) 
     
    1314 
    1415#define plugin_data mod_cache_plugin_data 
    15  
    16 typedef enum { UNSET, PART, TIMES, MINUS, PLUS, OR, AND, GT, LT, GE, LE, EQ, NE } tnode_op_t; 
    17  
    18 typedef enum { T_NODE_VALUE_UNSET, T_NODE_VALUE_LONG, T_NODE_VALUE_STRING } tnode_val_t; 
    19  
    20 typedef struct { 
    21         tnode_val_t type; 
    22          
    23         union { 
    24                 buffer *str; 
    25                 long    lon; 
    26         } data; 
    27 } tnode_val; 
    28  
    29 #define VAL_LONG(x) x->value.data.lon 
    30 #define VAL_STRING(x) x->value.data.str 
    31  
    32 #define IS_LONG(x) ((x->op == UNSET) && (x->value.type == T_NODE_VALUE_LONG)) 
    33 #define IS_STRING(x) ((x->op == UNSET) && (x->value.type == T_NODE_VALUE_STRING)) 
    34  
    35 typedef struct tnode { 
    36         tnode_val value; 
    37         tnode_op_t op; 
    38          
    39         struct tnode *l, *r; 
    40 } tnode; 
    41  
    42 typedef struct  { 
    43         tnode_val **ptr; 
    44          
    45         size_t size; 
    46         size_t used; 
    47 } tnode_val_array; 
    4816 
    4917typedef struct { 
     
    6735        buffer *session_id; 
    6836         
    69         buffer_array *eval; 
    70         buffer_array *trigger_if; 
    71         buffer_array *output_include; 
    72          
    73         tnode_val_array *params; 
    74          
    7537        plugin_config **config_storage; 
    7638         
     
    7840} plugin_data; 
    7941 
    80 typedef struct { 
    81         char *name; 
    82         size_t params; 
    83         int (*func)(server *srv, connection *con, plugin_data *p, tnode *result); 
    84 } cache_trigger_functions; 
    85  
    86 int cache_parse_parameters(server *srv, connection *con, plugin_data *p, const char *params, size_t param_len, tnode_val_array *res); 
    87 int cache_parse(server *srv, connection *con, plugin_data *p, buffer *fn); 
    88 int tnode_prepare_long(tnode *t); 
    89 int tnode_prepare_string(tnode *t); 
    90  
    91 tnode_val_array *tnode_val_array_init(); 
    92 void tnode_val_array_free(tnode_val_array *tva); 
    93 void tnode_val_array_reset(tnode_val_array *tva); 
    94  
    95 #define CACHE_FUNC_PROTO(x) int x(server *srv, connection *con, plugin_data *p, tnode *result) 
    96  
    97 CACHE_FUNC_PROTO(f_unix_time_now); 
    98 CACHE_FUNC_PROTO(f_file_mtime); 
    99 CACHE_FUNC_PROTO(f_memcache_exists); 
    100 CACHE_FUNC_PROTO(f_memcache_get_string); 
    101 CACHE_FUNC_PROTO(f_memcache_get_long); 
    102 CACHE_FUNC_PROTO(f_http_request_get_param); 
    103 CACHE_FUNC_PROTO(f_crypto_md5); 
     42int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn); 
    10443 
    10544#endif 
  • branches/lighttpd-1.3.x/src/mod_cml_funcs.c

    r445 r452  
    1515 
    1616#include "mod_cml.h" 
     17#include "mod_cml_funcs.h" 
    1718 
    1819#ifdef USE_OPENSSL 
     
    3435#define OUT 
    3536 
    36 CACHE_FUNC_PROTO(f_unix_time_now) { 
    37         UNUSED(srv); 
    38         UNUSED(con); 
    39         UNUSED(p); 
    40          
    41         VAL_LONG(result) = srv->cur_ts; 
    42          
    43         return 0; 
    44 } 
    45  
    46 CACHE_FUNC_PROTO(f_file_mtime) { 
    47         buffer *b; 
    48         struct stat st; 
    49          
    50         UNUSED(con); 
    51          
    52         if (p->params->ptr[0]->type != T_NODE_VALUE_STRING) { 
    53                 log_error_write(srv, __FILE__, __LINE__, "sd",  
    54                                 "f_file_mtime: I need a string:",  
    55                                 p->params->ptr[0]->type); 
    56                  
    57                 return -1; 
    58         } 
    59          
    60         b = buffer_init(); 
    61                          
    62         /* build filename */ 
    63         buffer_copy_string_buffer(b, p->basedir); 
    64         buffer_append_string_buffer(b, p->params->ptr[0]->data.str); 
    65          
    66         if (-1 == stat(b->ptr, &st)) { 
    67                 log_error_write(srv, __FILE__, __LINE__, "sbs",  
    68                                 "trigger.if file.mtime():", b, strerror(errno)); 
    69                  
    70                 buffer_free(b); 
    71                 return -1; 
    72         } 
    73         buffer_free(b); 
    74          
    75         tnode_prepare_long(result); 
    76         VAL_LONG(result) = st.st_mtime; 
    77          
    78         return 0; 
    79 } 
    80  
    81 int split_query_string(server *srv, connection *con, array *vals) { 
    82         size_t key_start = 0, key_end = 0,  
    83                 value_start = 0; 
    84         size_t is_key = 1; 
    85         size_t i; 
    86          
    87         for (i = 0; i < con->uri.query->used; i++) { 
    88                 switch(con->uri.query->ptr[i]) { 
    89                 case '=': 
    90                         if (is_key) { 
    91                                 key_end = i - 1; 
    92                                 value_start = i + 1; 
    93                                  
    94                                 is_key = 0; 
    95                         } 
    96                          
    97                         break; 
    98                 case '&': 
    99                 case '\0': /* fin symbol */ 
    100                         if (!is_key) { 
    101                                 data_string *ds; 
    102                                  
    103                                 /* we need at least a = since the last & */ 
    104                                  
    105                                 if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) { 
    106                                         ds = data_string_init(); 
    107                                 } 
    108                                  
    109                                 buffer_copy_string_len(ds->key,   con->uri.query->ptr + key_start, key_end - key_start); 
    110                                 buffer_copy_string_len(ds->value, con->uri.query->ptr + value_start, i - value_start); 
    111                                  
    112                                 array_insert_unique(vals, (data_unset *)ds); 
    113                         } 
    114                          
    115                         key_start = i + 1; 
    116                         value_start = 0; 
    117                         is_key = 1; 
    118                         break; 
    119                 } 
    120         } 
    121          
    122         return 0; 
    123 } 
    124  
    125  
    126 CACHE_FUNC_PROTO(f_http_request_get_param) { 
    127         array *qry_str; 
    128         data_string *ds; 
    129          
    130         /* fetch data from the con-> request query string */ 
    131          
    132         if (p->params->ptr[0]->type != T_NODE_VALUE_STRING) { 
    133                 log_error_write(srv, __FILE__, __LINE__, "sd",  
    134                                 "f_http_request_get_param: I need a string:",  
    135                                 p->params->ptr[0]->type); 
    136                  
    137                 return -1; 
    138         } 
    139          
    140         qry_str = array_init(); 
    141          
    142         split_query_string(srv, con, qry_str); 
    143          
    144         tnode_prepare_string(result); 
    145          
    146         if (NULL == (ds = (data_string *)array_get_element(qry_str, p->params->ptr[0]->data.str->ptr))) { 
    147                  
    148                 buffer_copy_string(VAL_STRING(result), ""); 
    149                  
    150                 array_free(qry_str); 
    151                  
    152                 return 0; 
    153         } 
    154          
    155         buffer_copy_string_buffer(VAL_STRING(result), ds->value); 
    156          
    157         array_free(qry_str); 
    158          
    159         return 0; 
    160 } 
    161  
    162 CACHE_FUNC_PROTO(f_crypto_md5) { 
     37#ifdef HAVE_LUA_H 
     38 
     39int f_crypto_md5(lua_State *L) { 
    16340        MD5_CTX Md5Ctx; 
    16441        HASH HA1; 
    165          
    166         /* fetch data from the con-> request query string */ 
    167          
    168         if (p->params->ptr[0]->type != T_NODE_VALUE_STRING) { 
    169                 log_error_write(srv, __FILE__, __LINE__, "sd",  
    170                                 "crypto.md5: I need a string:",  
    171                                 p->params->ptr[0]->type); 
    172                  
    173                 return -1; 
     42        buffer b; 
     43        char hex[33]; 
     44        int n = lua_gettop(L); 
     45         
     46        b.ptr = hex; 
     47        b.used = 0; 
     48        b.size = sizeof(hex); 
     49         
     50        if (n != 1) { 
     51                lua_pushstring(L, "expected one argument"); 
     52                lua_error(L); 
     53        } 
     54         
     55        if (!lua_isstring(L, 1)) { 
     56                lua_pushstring(L, "argument has to be a string"); 
     57                lua_error(L); 
    17458        } 
    17559         
    17660        MD5_Init(&Md5Ctx); 
    177         MD5_Update(&Md5Ctx, (unsigned char *)p->params->ptr[0]->data.str->ptr, p->params->ptr[0]->data.str->used - 1); 
     61        MD5_Update(&Md5Ctx, (unsigned char *)lua_tostring(L, 1), lua_strlen(L, 1)); 
    17862        MD5_Final(HA1, &Md5Ctx); 
    17963         
    180         tnode_prepare_string(result); 
    181         buffer_copy_string_hex(VAL_STRING(result), (char *)HA1, 16); 
    182          
    183         return 0; 
     64        buffer_copy_string_hex(&b, (char *)HA1, 16); 
     65         
     66        lua_pushstring(L, b.ptr); 
     67         
     68        return 1; 
     69} 
     70 
     71 
     72int f_file_mtime(lua_State *L) { 
     73        struct stat st; 
     74        int n = lua_gettop(L); 
     75         
     76        if (n != 1) { 
     77                lua_pushstring(L, "expected one argument"); 
     78                lua_error(L); 
     79        } 
     80         
     81        if (!lua_isstring(L, 1)) { 
     82                lua_pushstring(L, "argument has to be a string"); 
     83                lua_error(L); 
     84        } 
     85         
     86        if (-1 == stat(lua_tostring(L, 1), &st)) { 
     87                lua_pushstring(L, "stat failed"); 
     88                lua_error(L); 
     89        } 
     90         
     91        lua_pushnumber(L, st.st_mtime); 
     92         
     93        return 1; 
    18494} 
    18595 
    18696#ifdef HAVE_MEMCACHE_H 
    187 CACHE_FUNC_PROTO(f_memcache_exists) { 
     97int f_memcache_exists(lua_State *L) { 
    18898        char *r; 
    189          
    190         UNUSED(con); 
    191          
    192         if (!p->conf.mc) { 
    193                 log_error_write(srv, __FILE__, __LINE__, "sd",  
    194                                 "f_memcache_exists: no memcache.hosts set:",  
    195                                 p->params->ptr[0]->type); 
    196                 return -1; 
    197         } 
    198          
    199         if (p->params->ptr[0]->type != T_NODE_VALUE_STRING) { 
    200                 log_error_write(srv, __FILE__, __LINE__, "sd",  
    201                                 "f_memcache_exists: I need a string:",  
    202                                 p->params->ptr[0]->type); 
    203                  
    204                 return -1; 
    205         } 
    206          
    207         tnode_prepare_long(result); 
    208          
    209         if (NULL == (r = mc_aget(p->conf.mc,  
    210                                  CONST_BUF_LEN(p->params->ptr[0]->data.str)))) { 
     99        int n = lua_gettop(L); 
     100        struct memcache *mc; 
     101         
     102        if (!lua_islightuserdata(L, lua_upvalueindex(1))) { 
     103                lua_pushstring(L, "where is my userdata ?"); 
     104                lua_error(L); 
     105        } 
     106         
     107        mc = lua_touserdata(L, lua_upvalueindex(1)); 
     108         
     109        if (n != 1) { 
     110                lua_pushstring(L, "expected one argument"); 
     111                lua_error(L); 
     112        } 
     113         
     114        if (!lua_isstring(L, 1)) { 
     115                lua_pushstring(L, "argument has to be a string"); 
     116                lua_error(L); 
     117        } 
     118         
     119        if (NULL == (r = mc_aget(mc,  
     120                                 lua_tostring(L, 1), lua_strlen(L, 1)))) { 
    211121                                 
    212                 VAL_LONG(result) = 0; 
    213                 return 0; 
     122                lua_pushboolean(L, 0); 
     123                return 1; 
    214124        } 
    215125         
    216126        free(r); 
    217127         
    218         VAL_LONG(result) = 1; 
    219          
    220         return 0; 
    221 } 
    222  
    223 CACHE_FUNC_PROTO(f_memcache_get_string) { 
     128        lua_pushboolean(L, 1); 
     129        return 1; 
     130} 
     131 
     132int f_memcache_get_string(lua_State *L) { 
    224133        char *r; 
    225          
    226         UNUSED(con); 
    227          
    228         if (!p->conf.mc) { 
    229                 log_error_write(srv, __FILE__, __LINE__, "sd",  
    230                                 "f_memcache_get_string: no memcache.hosts set:",  
    231                                 p->params->ptr[0]->type); 
    232                 return -1; 
    233         } 
    234          
    235         if (p->params->ptr[0]->type != T_NODE_VALUE_STRING) { 
    236                 log_error_write(srv, __FILE__, __LINE__, "sd",  
    237                                 "f_memcache_get_string: I need a string:",  
    238                                 p->params->ptr[0]->type); 
    239                 return -1; 
    240         } 
    241          
    242         if (NULL == (r = mc_aget(p->conf.mc,  
    243                                  p->params->ptr[0]->data.str->ptr, p->params->ptr[0]->data.str->used - 1))) { 
    244                 log_error_write(srv, __FILE__, __LINE__, "sb",  
    245                                 "f_memcache_get_string: couldn't find:",  
    246                                 p->params->ptr[0]->data.str); 
    247                 return -1; 
    248         } 
    249         tnode_prepare_string(result); 
    250         buffer_copy_string(VAL_STRING(result), r); 
     134        int n = lua_gettop(L); 
     135         
     136        struct memcache *mc; 
     137         
     138        if (!lua_islightuserdata(L, lua_upvalueindex(1))) { 
     139                lua_pushstring(L, "where is my userdata ?"); 
     140                lua_error(L); 
     141        } 
     142         
     143        mc = lua_touserdata(L, lua_upvalueindex(1)); 
     144         
     145         
     146        if (n != 1) { 
     147                lua_pushstring(L, "expected one argument"); 
     148                lua_error(L); 
     149        } 
     150         
     151        if (!lua_isstring(L, 1)) { 
     152                lua_pushstring(L, "argument has to be a string"); 
     153                lua_error(L); 
     154        } 
     155         
     156        if (NULL == (r = mc_aget(mc,  
     157                                 lua_tostring(L, 1), lua_strlen(L, 1)))) { 
     158                lua_pushnil(L); 
     159                return 1; 
     160        } 
     161         
     162        lua_pushstring(L, r); 
    251163         
    252164        free(r); 
    253165         
    254         return 0; 
    255 } 
    256  
    257 CACHE_FUNC_PROTO(f_memcache_get_long) { 
     166        return 1; 
     167} 
     168 
     169int f_memcache_get_long(lua_State *L) { 
    258170        char *r; 
    259          
    260         UNUSED(con); 
    261          
    262         if (!p->conf.mc) { 
    263                 log_error_write(srv, __FILE__, __LINE__, "sd",  
    264