00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "memcached.h"
00028 #include "mcd_var.h"
00029
00030 #include "../../sr_module.h"
00031 #include "../../mem/mem.h"
00032 #include "../../dprint.h"
00033 #include "../../ut.h"
00034 #include "../../str.h"
00035
00036
00037 MODULE_VERSION
00038
00039
00040 #define DP_ALERT_TEXT "ALERT:"
00041 #define DP_ERR_TEXT "ERROR:"
00042 #define DP_WARN_TEXT "WARNING:"
00043 #define DP_NOTICE_TEXT "NOTICE:"
00044 #define DP_INFO_TEXT "INFO:"
00045
00046
00048 char* memcached_srv_str = "localhost:11211";
00050 unsigned int memcached_expire = 10800;
00052 unsigned int memcached_mode = 0;
00054 int memcached_timeout = 5000;
00056 struct memcache* memcached_h = NULL;
00057
00058
00059 static int mod_init(void);
00060
00061 static void mod_destroy(void);
00062
00063
00067 static pv_export_t mod_pvs[] = {
00068 { {"mct", sizeof("mct")-1}, PVT_OTHER, pv_get_mcd_value, pv_set_mcd_value,
00069 pv_parse_mcd_name, 0, 0, 0 },
00070 { {"mcinc", sizeof("mcinc")-1}, PVT_OTHER, pv_get_mcd_value, pv_inc_mcd_value,
00071 pv_parse_mcd_name, 0, 0, 0 },
00072 { {"mcdec", sizeof("mcdec")-1}, PVT_OTHER, pv_get_mcd_value, pv_dec_mcd_value,
00073 pv_parse_mcd_name, 0, 0, 0 },
00074 { {"mctex", sizeof("mctex")-1}, PVT_OTHER, pv_get_null, pv_set_mcd_expire,
00075 pv_parse_mcd_name, 0, 0, 0 },
00076 { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
00077 };
00078
00079
00083 static param_export_t params[] = {
00084 {"servers", STR_PARAM, &memcached_srv_str },
00085 {"expire", INT_PARAM, &memcached_expire },
00086 {"timeout", INT_PARAM, &memcached_timeout },
00087 {"mode", INT_PARAM, &memcached_mode },
00088 {0, 0, 0}
00089 };
00090
00091
00095 struct module_exports exports = {
00096 "memcached",
00097 DEFAULT_DLFLAGS,
00098 0,
00099 params,
00100 0,
00101 0,
00102 mod_pvs,
00103 0,
00104 mod_init,
00105 0,
00106 mod_destroy,
00107 0
00108 };
00109
00110
00116 static inline void memcached_free(void *mem) {
00117 pkg_free(mem);
00118 }
00119
00120
00127 static inline void* memcached_malloc(const size_t size) {
00128 return pkg_malloc(size);
00129 }
00130
00131
00139 static inline void* memcached_realloc(void *mem, const size_t size) {
00140 return pkg_realloc(mem, size);
00141 }
00142
00143
00147 static int memcache_err_func(MCM_ERR_FUNC_ARGS) {
00148
00149 const struct memcache_ctxt *ctxt;
00150 struct memcache_err_ctxt *ectxt;
00151 int error_level;
00152 const char * error_str;
00153
00154 MCM_ERR_INIT_CTXT(ctxt, ectxt);
00155
00156 switch (ectxt->severity) {
00157 case MCM_ERR_LVL_INFO:
00158 error_level = L_INFO;
00159 error_str = DP_INFO_TEXT;
00160 break;
00161 case MCM_ERR_LVL_NOTICE:
00162 error_level = L_NOTICE;
00163 error_str = DP_NOTICE_TEXT;
00164 break;
00165 case MCM_ERR_LVL_WARN:
00166 error_level = L_WARN;
00167 error_str = DP_WARN_TEXT;
00168 break;
00169 case MCM_ERR_LVL_ERR:
00170 error_level = L_ERR;
00171 error_str = DP_ERR_TEXT;
00172
00173 ectxt->cont = 'y';
00174 break;
00175 case MCM_ERR_LVL_FATAL:
00176 default:
00177 error_level = L_ALERT;
00178 error_str = DP_ALERT_TEXT;
00179 ectxt->cont = 'y';
00180 break;
00181 }
00182
00183
00184
00185
00186
00187 if (ectxt->errstr != NULL && ectxt->errmsg != NULL)
00188 LM_GEN1(error_level, "%s memcached: %s():%u: %s: %.*s\n", error_str, ectxt->funcname, ectxt->lineno, ectxt->errstr,
00189 (int)ectxt->errlen, ectxt->errmsg);
00190 else if (ectxt->errstr == NULL && ectxt->errmsg != NULL)
00191 LM_GEN1(error_level, "%s memcached: %s():%u: %.*s\n", error_str, ectxt->funcname, ectxt->lineno, (int)ectxt->errlen,
00192 ectxt->errmsg);
00193 else if (ectxt->errstr != NULL && ectxt->errmsg == NULL)
00194 LM_GEN1(error_level, "%s memcached: %s():%u: %s\n", error_str, ectxt->funcname, ectxt->lineno, ectxt->errstr);
00195 else
00196 LM_GEN1(error_level, "%s memcached: %s():%u\n", error_str, ectxt->funcname, ectxt->lineno);
00197
00198 return 0;
00199 }
00200
00201
00206 static int mod_init(void) {
00207 char *server, *port;
00208 unsigned int len = 0;
00209
00210
00211 if (mcMemSetup(memcached_free, memcached_malloc,
00212 memcached_malloc, memcached_realloc) != 0) {
00213 LM_ERR("could not setup memory management callbacks\n");
00214 return -1;
00215 }
00216
00217 if (mcErrSetup(memcache_err_func) != 0) {
00218 LM_ERR("could not setup error handler callback\n");
00219 return -1;
00220 }
00221
00223 mc_err_filter_del(MCM_ERR_LVL_INFO);
00224 mc_err_filter_del(MCM_ERR_LVL_NOTICE);
00225
00226 memcached_h = mc_new();
00227 if (memcached_h == NULL) {
00228 PKG_MEM_ERROR;
00229 return -1;
00230 }
00231
00232 if ((port = strchr(memcached_srv_str, ':')) != NULL) {
00233 port = port + 1;
00234 len = strlen(memcached_srv_str) - strlen(port) - 1;
00235 } else {
00236 LM_DBG("no port definition, using default port\n");
00237 port = "11211";
00238 len = strlen(memcached_srv_str) ;
00239 }
00240
00241
00242 server = pkg_malloc(len);
00243 if (server == NULL) {
00244 PKG_MEM_ERROR;
00245 return -1;
00246 }
00247
00248 strncpy(server, memcached_srv_str, len);
00249 server[len] = '\0';
00250
00251 mc_timeout(memcached_h, 0, memcached_timeout);
00252
00253 if (mc_server_add(memcached_h, server, port) != 0) {
00254 LM_ERR("could not add server %s:%s\n", server, port);
00255 return -1;
00256 }
00257 LM_INFO("connected to server %s:%s\n", server, port);
00258 pkg_free(server);
00259
00260 LM_INFO("memcached client version is %s, released on %d\n", mc_version(), mc_reldate());
00261 return 0;
00262 }
00263
00264
00268 static void mod_destroy(void) {
00269 if (memcached_h != NULL)
00270 mc_server_disconnect_all(memcached_h);
00271
00272 if (memcached_h != NULL)
00273 mc_free(memcached_h);
00274 }