memcached.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Copyright (C) 2009 Henning Westerholt
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License along
00019  * with this program; if not, see <http://www.gnu.org/licenses/>.
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                         /* try to continue */
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         * ectxt->errmsg - per error message passed along via one of the MCM_*_MSG() macros (optional)
00185         * ectxt->errstr - memcache error string (optional, though almost always set)
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         /* setup the callbacks to our internal memory manager */
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 }