Changeset 452
- Timestamp:
- 07/15/2005 05:46:13 PM (3 years ago)
- Location:
- branches/lighttpd-1.3.x
- Files:
-
- 6 modified
-
configure.in (modified) (1 diff)
-
doc/cml.txt (modified) (4 diffs)
-
src/Makefile.am (modified) (1 diff)
-
src/mod_cml.c (modified) (7 diffs)
-
src/mod_cml.h (modified) (4 diffs)
-
src/mod_cml_funcs.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/lighttpd-1.3.x/configure.in
r436 r452 272 272 ],[AC_MSG_RESULT(no)]) 273 273 AC_SUBST(MEMCACHE_LIB) 274 274 275 AC_MSG_CHECKING(for lua) 276 AC_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)]) 286 AC_SUBST(LUA_LIB) 287 275 288 276 289 AC_SEARCH_LIBS(socket,socket) -
branches/lighttpd-1.3.x/doc/cml.txt
r427 r452 12 12 13 13 :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. 15 15 16 16 .. meta:: 17 :keywords: lighttpd, cml 17 :keywords: lighttpd, cml, lua 18 18 19 19 .. contents:: Table of Contents … … 98 98 and the following index.cml file: :: 99 99 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 108 116 109 117 Numbers again: … … 133 141 The index.cml for this looks like: :: 134 142 135 output.content-type text/html 143 output_content_type = "text/html" 144 145 cwd = request["CWD"] 136 146 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 144 156 145 157 Now we get about 10000 req/s instead of 600 req/s. … … 150 162 :cml.extension: 151 163 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) 152 168 153 169 Language 154 170 ======== 155 171 156 ... will come later ... 172 The language used for CML is provided by `LUA <http://www.lua.org/>`_. 173 174 Additionally 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 198 What ever your script does, it has to return either 0 or 1 for ``cache-hit`` or ``cache-miss``. 199 It case a error occures check the error-log, the user will get a error 500. If you don't like 200 the standard error-page use ``server.errorfile-prefix``. 201 202 Examples 203 ======== 204 205 Using 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 218 In MySQL you do: :: 219 220 SELECT memcache_set("127.0.0.1:11211", "123", "12"); 221 222 or to retrieve a value: 223 224 SELECT memcache_get("127.0.0.1:11211", "123"); 225 226 You 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 70 70 71 71 lib_LTLIBRARIES += mod_cml.la 72 mod_cml_la_SOURCES = mod_cml.c mod_cml_ funcs.c mod_cml_logic.c72 mod_cml_la_SOURCES = mod_cml.c mod_cml_lua.c mod_cml_funcs.c 73 73 mod_cml_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined 74 mod_cml_la_LIBADD = $(MEMCACHE_LIB) $(common_libadd) 74 mod_cml_la_LIBADD = $(MEMCACHE_LIB) $(common_libadd) $(LUA_LIB) 75 75 76 76 lib_LTLIBRARIES += mod_trigger_b4_dl.la -
branches/lighttpd-1.3.x/src/mod_cml.c
r440 r452 29 29 p->trigger_handler = buffer_init(); 30 30 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 36 31 return p; 37 32 } … … 63 58 free(p->config_storage); 64 59 } 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);71 60 72 61 buffer_free(p->trigger_handler); … … 104 93 s->mc_hosts = array_init(); 105 94 s->mc_namespace = buffer_init(); 95 #if defined(HAVE_MEMCACHE_H) 96 s->mc = NULL; 97 #endif 106 98 107 99 cv[0].destination = s->ext; … … 323 315 plugin_data *p = p_d; 324 316 size_t i; 317 int ret; 325 318 326 319 if (fn->used == 0) return HANDLER_ERROR; … … 332 325 mod_cml_patch_connection(srv, con, p, CONST_BUF_LEN(patch)); 333 326 } 334 335 buffer_array_reset(p->output_include);336 buffer_array_reset(p->eval);337 buffer_array_reset(p->trigger_if);338 327 339 328 buffer_reset(p->basedir); … … 341 330 buffer_reset(p->session_id); 342 331 buffer_reset(p->trigger_handler); 343 344 tnode_val_array_reset(p->params);345 332 346 333 if (buffer_is_empty(p->conf.ext)) return HANDLER_GO_ON; … … 383 370 cache_get_session_id(srv, con, p); 384 371 385 switch(cache_parse(srv, con, p, fn)) { 372 ret = cache_parse_lua(srv, con, p, fn); 373 374 switch(ret) { 386 375 case -1: 387 376 /* error */ -
branches/lighttpd-1.3.x/src/mod_cml.h
r441 r452 7 7 8 8 #include "stream.h" 9 #include "plugin.h" 9 10 10 11 #if defined(HAVE_MEMCACHE_H) … … 13 14 14 15 #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.lon30 #define VAL_STRING(x) x->value.data.str31 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;48 16 49 17 typedef struct { … … 67 35 buffer *session_id; 68 36 69 buffer_array *eval;70 buffer_array *trigger_if;71 buffer_array *output_include;72 73 tnode_val_array *params;74 75 37 plugin_config **config_storage; 76 38 … … 78 40 } plugin_data; 79 41 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); 42 int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn); 104 43 105 44 #endif -
branches/lighttpd-1.3.x/src/mod_cml_funcs.c
r445 r452 15 15 16 16 #include "mod_cml.h" 17 #include "mod_cml_funcs.h" 17 18 18 19 #ifdef USE_OPENSSL … … 34 35 #define OUT 35 36 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 39 int f_crypto_md5(lua_State *L) { 163 40 MD5_CTX Md5Ctx; 164 41 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); 174 58 } 175 59 176 60 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)); 178 62 MD5_Final(HA1, &Md5Ctx); 179 63 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 72 int 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; 184 94 } 185 95 186 96 #ifdef HAVE_MEMCACHE_H 187 CACHE_FUNC_PROTO(f_memcache_exists) {97 int f_memcache_exists(lua_State *L) { 188 98 char *r; 189 190 UNUSED(con);191 192 if (! p->conf.mc) {193 l og_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 l og_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)))) { 211 121 212 VAL_LONG(result) = 0;213 return 0;122 lua_pushboolean(L, 0); 123 return 1; 214 124 } 215 125 216 126 free(r); 217 127 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 132 int f_memcache_get_string(lua_State *L) { 224 133 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); 251 163 252 164 free(r); 253 165 254 return 0;255 } 256 257 CACHE_FUNC_PROTO(f_memcache_get_long) {166 return 1; 167 } 168 169 int f_memcache_get_long(lua_State *L) { 258 170 char *r; 259 260 UNUSED(con); 261 262 if (!p->conf.mc) { 263 log_error_write(srv, __FILE__, __LINE__, "sd", 264
