diff options
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/mod_cml.c | 38 | ||||
-rw-r--r-- | src/mod_cml.h | 12 | ||||
-rw-r--r-- | src/mod_cml_funcs.c | 67 | ||||
-rw-r--r-- | src/mod_cml_logic.c | 15 |
5 files changed, 121 insertions, 13 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 7d01d0be..be69b28d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -71,7 +71,7 @@ endif lib_LTLIBRARIES += mod_cml.la mod_cml_la_SOURCES = mod_cml.c mod_cml_funcs.c mod_cml_logic.c mod_cml_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined -mod_cml_la_LIBADD = $(MYSQL_LIBS) $(common_libadd) +mod_cml_la_LIBADD = $(MEMCACHE_LIB) $(common_libadd) lib_LTLIBRARIES += mod_trigger_b4_dl.la mod_trigger_b4_dl_la_SOURCES = mod_trigger_b4_dl.c diff --git a/src/mod_cml.c b/src/mod_cml.c index acae66f6..640415b5 100644 --- a/src/mod_cml.c +++ b/src/mod_cml.c @@ -50,6 +50,13 @@ FREE_FUNC(mod_cml_free) { buffer_free(s->ext); + buffer_free(s->mc_namespace); + array_free(s->mc_hosts); + +#if defined(HAVE_MEMCACHE_H) + if (s->mc) mc_free(s->mc); +#endif + free(s); } free(p->config_storage); @@ -77,7 +84,9 @@ SETDEFAULTS_FUNC(mod_cml_set_defaults) { size_t i = 0; config_values_t cv[] = { - { "cml.extension", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ + { "cml.extension", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ + { "cml.memcache-hosts", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ + { "cml.memcache-namespace", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; @@ -90,14 +99,41 @@ SETDEFAULTS_FUNC(mod_cml_set_defaults) { s = malloc(sizeof(plugin_config)); s->ext = buffer_init(); + s->mc_hosts = array_init(); + s->mc_namespace = buffer_init(); cv[0].destination = s->ext; + cv[1].destination = s->mc_hosts; + cv[2].destination = s->mc_namespace; p->config_storage[i] = s; if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) { return HANDLER_ERROR; } + + if (s->mc_hosts->used) { +#if defined(HAVE_MEMCACHE_H) + size_t k; + s->mc = mc_new(); + + for (k = 0; k < s->mc_hosts->used; k++) { + data_string *ds = (data_string *)s->mc_hosts->data[k]; + + if (0 != mc_server_add4(s->mc, ds->value->ptr)) { + log_error_write(srv, __FILE__, __LINE__, "sb", + "connection to host failed:", + ds->value); + + return HANDLER_ERROR; + } + } +#else + log_error_write(srv, __FILE__, __LINE__, "s", + "memcache support is not compiled in but cml.memcache-hosts is set, aborting"); + return HANDLER_ERROR; +#endif + } } return HANDLER_GO_ON; diff --git a/src/mod_cml.h b/src/mod_cml.h index 45b3c062..89cd09e9 100644 --- a/src/mod_cml.h +++ b/src/mod_cml.h @@ -7,6 +7,10 @@ #include "stream.h" +#if defined(HAVE_MEMCACHE_H) +#include <memcache.h> +#endif + #define plugin_data mod_cache_plugin_data typedef enum { UNSET, PART, TIMES, MINUS, PLUS, OR, AND, GT, LT, GE, LE, EQ, NE } tnode_op_t; @@ -45,6 +49,11 @@ typedef struct { typedef struct { buffer *ext; + array *mc_hosts; + buffer *mc_namespace; +#if defined(HAVE_MEMCACHE_H) + struct memcache *mc; +#endif } plugin_config; typedef struct { @@ -86,7 +95,8 @@ void tnode_val_array_reset(tnode_val_array *tva); CACHE_FUNC_PROTO(f_unix_time_now); CACHE_FUNC_PROTO(f_file_mtime); -CACHE_FUNC_PROTO(f_memcache_get); CACHE_FUNC_PROTO(f_memcache_exists); +CACHE_FUNC_PROTO(f_memcache_get_string); +CACHE_FUNC_PROTO(f_memcache_get_long); #endif diff --git a/src/mod_cml_funcs.c b/src/mod_cml_funcs.c index 43db70d9..902fd5a6 100644 --- a/src/mod_cml_funcs.c +++ b/src/mod_cml_funcs.c @@ -61,8 +61,10 @@ CACHE_FUNC_PROTO(f_file_mtime) { return 0; } +#ifdef HAVE_MEMCACHE_H CACHE_FUNC_PROTO(f_memcache_exists) { - UNUSED(srv); + char *r; + UNUSED(con); if (p->params->ptr[0]->type != T_NODE_VALUE_STRING) { @@ -74,13 +76,24 @@ CACHE_FUNC_PROTO(f_memcache_exists) { } tnode_prepare_long(result); - VAL_LONG(result) = 0; + + if (NULL == (r = mc_aget(p->conf.mc, + CONST_BUF_LEN(p->params->ptr[0]->data.str)))) { + + VAL_LONG(result) = 0; + return 0; + } + + free(r); + + VAL_LONG(result) = 1; return 0; } -CACHE_FUNC_PROTO(f_memcache_get) { - UNUSED(srv); +CACHE_FUNC_PROTO(f_memcache_get_string) { + char *r; + UNUSED(con); if (p->params->ptr[0]->type != T_NODE_VALUE_STRING) { @@ -90,8 +103,52 @@ CACHE_FUNC_PROTO(f_memcache_get) { return -1; } + log_error_write(srv, __FILE__, __LINE__, "sb", + "f_memcache_get: couldn't find:", + p->params->ptr[0]->data.str); + + if (NULL == (r = mc_aget(p->conf.mc, + p->params->ptr[0]->data.str->ptr, p->params->ptr[0]->data.str->used - 1))) { + log_error_write(srv, __FILE__, __LINE__, "sb", + "f_memcache_get: couldn't find:", + p->params->ptr[0]->data.str); + return -1; + } tnode_prepare_string(result); - buffer_copy_string_buffer(VAL_STRING(result), p->params->ptr[0]->data.str); + buffer_copy_string(VAL_STRING(result), r); + + free(r); + + return 0; +} + +CACHE_FUNC_PROTO(f_memcache_get_long) { + char *r; + + UNUSED(con); + + if (p->params->ptr[0]->type != T_NODE_VALUE_STRING) { + log_error_write(srv, __FILE__, __LINE__, "sd", + "f_memcache_get: I need a string:", + p->params->ptr[0]->type); + return -1; + } + + + + if (NULL == (r = mc_aget(p->conf.mc, + CONST_BUF_LEN(p->params->ptr[0]->data.str)))) { + log_error_write(srv, __FILE__, __LINE__, "sb", + "f_memcache_get: couldn't find:", + p->params->ptr[0]->data.str); + return -1; + } + + tnode_prepare_long(result); + VAL_LONG(result) = strtol(r, NULL, 10); + + free(r); return 0; } +#endif diff --git a/src/mod_cml_logic.c b/src/mod_cml_logic.c index 2a47e8e9..313a9ce1 100644 --- a/src/mod_cml_logic.c +++ b/src/mod_cml_logic.c @@ -165,8 +165,11 @@ int cache_trigger_parse(server *srv, connection *con, plugin_data *p, buffer *t cache_trigger_functions f[] = { { "file.mtime", 1, f_file_mtime }, { "unix.time.now", 0, f_unix_time_now }, +#ifdef HAVE_MEMCACHE_H { "memcache.exits", 1, f_memcache_exists }, - { "memcache.get", 1, f_memcache_get }, + { "memcache.get_string", 1, f_memcache_get_string }, + { "memcache.get_long", 1, f_memcache_get_long }, +#endif { NULL, 0, NULL }, }; @@ -480,12 +483,13 @@ int cache_trigger_eval(server *srv, connection *con, plugin_data *p, tnode *t) { } } else if (IS_STRING(t->l) && IS_STRING(t->r)) { if (-1 == cache_ops_string(t, t->l, t->r)) { - fprintf(stderr, "%s.%d: cache_ops_string failed\n", __FILE__, __LINE__); + log_error_write(srv, __FILE__, __LINE__, "s", + "cache_ops_string failed"); return -1; } } else { - fprintf(stderr, "%s.%d: typemismatch\n", - __FILE__, __LINE__); + log_error_write(srv, __FILE__, __LINE__, "s", + "typemismatch"); return -1; } @@ -505,7 +509,8 @@ int cache_trigger(server *srv, connection *con, plugin_data *p) { } if (-1 == cache_trigger_eval(srv, con, p, t)) { - fprintf(stderr, "%s.%d: cache_trigger_eval failed\n", __FILE__, __LINE__); + log_error_write(srv, __FILE__, __LINE__, "s", + "cache_trigger_eval failed"); return -1; } |