Browse code

memcached: port module to use the newer libmemcached library * based on a patch from Charles Chance, sipcentric.com * He added new functionality to set the expiry directly in the key * Added memory manager wrapping functions and some more logging, * smaller cleanups in the code structure * This is work in progress, the memory management stuff is not yet * finished, as this needs different logic for client lib version * before and after 0.32. It will not work at the moment correctly.

Henning Westerholt authored on 21/04/2013 19:56:28
Showing 5 changed files
... ...
@@ -9,6 +9,6 @@ NAME=memcached.so
9 9
 DEFS+=-DKAMAILIO_MOD_INTERFACE
10 10
 
11 11
 DEFS +=-I$(LOCALBASE)/include -I$(SYSBASE)/include
12
-LIBS+=-L$(LOCALBASE)/lib -L$(SYSBASE)/lib -lmemcache
12
+LIBS+=-L$(LOCALBASE)/lib -L$(SYSBASE)/lib -lmemcached
13 13
 
14 14
 include ../../Makefile.modules
... ...
@@ -1,7 +1,6 @@
1
-/**
2
- * $Id$
3
- *
4
- * Copyright (C) 2009 Henning Westerholt
1
+/*
2
+ * Copyright (C) 2009, 2013 Henning Westerholt
3
+ * Copyright (C) 2013 Charles Chance, sipcentric.com
5 4
  *
6 5
  * This file is part of Kamailio, a free SIP server.
7 6
  *
... ...
@@ -34,15 +33,73 @@
34 34
 
35 35
 
36 36
 /*!
37
- * \brief Checks if the key is avaiable and not too long, hash it with MD5 if necessary
37
+ * \brief Checks for '=>' delimiter in key name string and if present, extracts expiry value.
38
+ * \param data string to parse
39
+ * \param key output string name
40
+ * \param exp output int expiry (if present)
41
+ * \return 0 on success, negative on failure
42
+ */
43
+static inline int pv_mcd_key_expiry_split_str(str *data, str *key, unsigned int *exp) {
44
+	char *p;
45
+	str str_exp;
46
+	
47
+	if (data == NULL || data->s == NULL || data->len <= 0) {
48
+		LM_ERR("invalid parameters\n");
49
+		return -1;
50
+	}
51
+	
52
+	p = data->s;
53
+	key->s = p;
54
+	key->len = 0;
55
+
56
+	while(p < data->s + data->len) {
57
+		if (*p == '=') {
58
+			p++;
59
+			if (*p == '>') {
60
+				break;
61
+			} else {
62
+				key->len++;
63
+			}
64
+		} else {
65
+	                key->len++;
66
+			p++;
67
+		}
68
+	}
69
+
70
+	if (key->len < data->len) {
71
+		/* delimiter is present, try to extract expiry value */
72
+		p++;
73
+		if (p < data->s + data->len) {
74
+			str_exp.s = p;
75
+			str_exp.len = 0;
76
+			while(p<data->s+data->len) {
77
+				str_exp.len++;
78
+				p++;
79
+			}
80
+		}
81
+		if (str_exp.len > 0) {
82
+			/* convert to int */
83
+			*exp = atoi(str_exp.s);
84
+		}
85
+		LM_DBG("key is %.*s expiry is %d\n", key->len, key->s, *exp);
86
+	}
87
+
88
+	return 0;
89
+}
90
+
91
+/*!
92
+ * \brief Checks if the key is avaiable and not too long, hashing it with MD5 if necessary.
38 93
  * \param msg SIP message
39 94
  * \param param pseudo-variable input parameter
40
- * \param out output string
95
+ * \param key output string name
96
+ * \param exp output int expiry (if present)
41 97
  * \return 0 on success, negative on failure
42 98
  */
43
-static inline int pv_mcd_key_check(struct sip_msg *msg, pv_param_t *param, str * out) {
99
+static inline int pv_mcd_key_check(struct sip_msg *msg, pv_param_t *param, str * key, unsigned int * exp ) {
44 100
 
101
+	str pvn;
45 102
 	str tmp;
103
+
46 104
 	static char hash[32];
47 105
 
48 106
 	if (msg == NULL || param == NULL) {
... ...
@@ -50,20 +107,24 @@ static inline int pv_mcd_key_check(struct sip_msg *msg, pv_param_t *param, str *
50 50
 		return -1;
51 51
 	}
52 52
 
53
-	if (pv_printf_s(msg, param->pvn.u.dname, &tmp) != 0)
53
+	if (pv_printf_s(msg, param->pvn.u.dname, &pvn) != 0)
54 54
 	{
55
-		LM_ERR("cannot get key name\n");
55
+		LM_ERR("cannot get pv name\n");
56
+		return -1;
57
+	}
58
+
59
+	if (pv_mcd_key_expiry_split_str(&pvn, &tmp, exp) != 0) {
56 60
 		return -1;
57 61
 	}
58 62
 
59 63
 	if (tmp.len < 250) {
60
-		out->s = tmp.s;
61
-		out->len = tmp.len;
64
+		key->s = tmp.s;
65
+		key->len = tmp.len;
62 66
 	} else {
63 67
 		LM_DBG("key too long (%d), hash it\n", tmp.len);
64 68
 		MD5StringArray (hash, &tmp, 1);
65
-		out->s = hash;
66
-		out->len = 32;
69
+		key->s = hash;
70
+		key->len = 32;
67 71
 	}
68 72
 	return 0;
69 73
 }
... ...
@@ -72,39 +133,33 @@ static inline int pv_mcd_key_check(struct sip_msg *msg, pv_param_t *param, str *
72 72
  * \brief Helper to get a cached value from memcached
73 73
  * \param msg SIP message
74 74
  * \param key value key
75
- * \param mcd_req request
76
- * \param mcd_res result
75
+ * \param return_value returned value
76
+ * \param flags returned flags
77 77
  * \return null on success, negative on failure
78 78
  */
79 79
 static int pv_get_mcd_value_helper(struct sip_msg *msg, str *key,
80
-		struct memcache_req **mcd_req, struct memcache_res **mcd_res) {
80
+		char **return_value, uint32_t *flags) {
81 81
 
82
-	/* we don't use mc_aget here, because we're multi-process */
83
-	if ( (*mcd_req = mc_req_new()) == NULL) {
84
-		PKG_MEM_ERROR;
85
-		return -1;
86
-	}
87
-	LM_DBG("allocate new memcache request at %p\n", *mcd_req);
82
+	memcached_return rc;
83
+	size_t return_value_length;
88 84
 
89
-	if ( (*mcd_res = mc_req_add(*mcd_req, key->s, key->len)) == NULL) {
90
-		PKG_MEM_ERROR;
91
-		return -1;
92
-	}
93
-	LM_DBG("allocate new memcache result at %p\n", *mcd_res);
85
+	*return_value = memcached_get(memcached_h, key->s, key->len, &return_value_length, flags, &rc);
94 86
 
95
-	mc_get(memcached_h, *mcd_req);
96
-	if (! ( (*mcd_res)->_flags & MCM_RES_FOUND)) {
97
-		LM_ERR("could not get result for key %.*s\n", key->len, key->s);
98
-		LM_DBG("free memcache request and result at %p\n", mcd_req);
99
-		mc_req_free(*mcd_req);
87
+	if (*return_value == NULL) {
88
+		if (rc == MEMCACHED_NOTFOUND) {
89
+			LM_DBG("key %.*s not found\n", key->len, key->s);
90
+		} else {
91
+			LM_ERR("could not get result for key %.*s - error was '%s'\n", key->len, key->s, memcached_strerror(memcached_h, rc));
92
+		}
100 93
 		return -1;
101 94
 	}
102
-	LM_DBG("result: %.*s for key %.*s with flag %d\n", (*mcd_res)->bytes, (char*)(*mcd_res)->val,
103
-		key->len, key->s, (*mcd_res)->flags);
95
+
96
+	LM_DBG("result: %s for key %.*s with flag %d\n", *return_value, key->len, key->s, *flags);
104 97
 
105 98
 	return 0;
106 99
 }
107 100
 
101
+
108 102
 /*!
109 103
  * \brief Get a cached value from memcached
110 104
  * \param msg SIP message
... ...
@@ -116,26 +171,32 @@ int pv_get_mcd_value(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) {
116 116
 
117 117
 	unsigned int res_int = 0;
118 118
 	str key, res_str;
119
-	struct memcache_req *mcd_req = NULL;
120
-	struct memcache_res *mcd_res = NULL;
119
+	unsigned int expiry = mcd_expire;
121 120
 
122
-	if (pv_mcd_key_check(msg, param, &key) < 0) {
121
+  	char *return_value;
122
+	uint32_t return_flags;
123
+
124
+	if (pv_mcd_key_check(msg, param, &key, &expiry) < 0) {
123 125
 		return pv_get_null(msg, param, res);
124 126
 	}
125 127
 
126 128
 	if (res==NULL)
127 129
 		return pv_get_null(msg, param, res);
128 130
 
129
-	if (pv_get_mcd_value_helper(msg, &key, &mcd_req, &mcd_res) < 0) {
131
+	if (pv_get_mcd_value_helper(msg, &key, &return_value, &return_flags) < 0) {
130 132
 		return pv_get_null(msg, param, res);
131 133
 	}
132 134
 
133
-	res_str.len = mcd_res->bytes;
134
-	res_str.s = mcd_res->val;
135
+
136
+	res_str.len = strlen(return_value);
137
+	res_str.s = return_value;
138
+
139
+
135 140
 	/* apparently memcached adds whitespaces to the beginning of the value after atomic operations */
141
+
136 142
 	trim_len(res_str.len, res_str.s, res_str);
137 143
 
138
-	if(mcd_res->flags&VAR_VAL_STR) {
144
+	if(return_flags&VAR_VAL_STR) {
139 145
 		 if (pkg_str_dup(&(res->rs), &res_str) < 0) {
140 146
 			LM_ERR("could not copy string\n");
141 147
 			goto errout;
... ...
@@ -150,18 +211,15 @@ int pv_get_mcd_value(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) {
150 150
 		res->ri = res_int;
151 151
 		res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
152 152
 	}
153
-	LM_DBG("free memcache request and result at %p\n", mcd_req);
154
-	mc_req_free(mcd_req);
155 153
 
156 154
 	return 0;
157 155
 
158 156
 errout:
159
-	LM_DBG("free memcache request and result at %p\n", mcd_req);
160
-	mc_req_free(mcd_req);
161 157
 	return pv_get_null(msg, param, res);
162 158
 }
163 159
 
164 160
 
161
+
165 162
 /*!
166 163
  * \brief Set a value in the cache of memcached
167 164
  * \todo Replacement of already existing values is not done atomically at the moment.
... ...
@@ -176,16 +234,18 @@ errout:
176 176
 
177 177
 	unsigned int val_flag = 0;
178 178
 	str val_str, key;
179
+	unsigned int expiry = mcd_expire;
179 180
 
180
-	if (pv_mcd_key_check(msg, param, &key) < 0)
181
+	if (pv_mcd_key_check(msg, param, &key, &expiry) < 0)
181 182
 		return -1;
182 183
 
183 184
 	if (val == NULL) {
184
-		if (mc_delete(memcached_h, key.s, key.len, 0) != 0) {
185
+		if (memcached_delete(memcached_h, key.s, key.len, 0) != MEMCACHED_SUCCESS) {
185 186
 			LM_ERR("could not delete key %.*s\n", param->pvn.u.isname.name.s.len,
186 187
 				param->pvn.u.isname.name.s.s);
188
+			return -1;
187 189
 		}
188
-		LM_DBG("delete key %.*s\n", key.len, key.s);
190
+		LM_WARN("delete key %.*s\n", key.len, key.s);
189 191
 		return 0;
190 192
 	}
191 193
 
... ...
@@ -196,13 +256,13 @@ errout:
196 196
 		val_flag = VAR_VAL_STR;
197 197
 	}
198 198
 
199
-	if (memcached_mode == 0) {
200
-		if (mc_set(memcached_h, key.s, key.len, val_str.s, val_str.len, memcached_expire, val_flag) != 0) {
199
+	if (mcd_mode == 0) {
200
+		if (memcached_set(memcached_h, key.s, key.len, val_str.s, val_str.len, expiry, val_flag) != MEMCACHED_SUCCESS) {
201 201
 			LM_ERR("could not set value for key %.*s\n", key.len, key.s);
202 202
 			return -1;
203 203
 		}
204 204
 	} else {
205
-		if (mc_add(memcached_h, key.s, key.len, val_str.s, val_str.len, memcached_expire, val_flag) != 0) {
205
+		if (memcached_add(memcached_h, key.s, key.len, val_str.s, val_str.len, expiry, val_flag) != MEMCACHED_SUCCESS) {
206 206
 			LM_ERR("could not add value for key %.*s\n", key.len, key.s);
207 207
 			return -1;
208 208
 		}
... ...
@@ -223,44 +283,41 @@ errout:
223 223
  * \param param parameter
224 224
  * \param op not used
225 225
  * \param val value
226
- * \param atomic_ops function pointer to the atomic operation from the memcache library
226
+ * \param atomic_ops function pointer to the atomic operation from the memcached library
227 227
  * \return 0 on success, -1 on failure
228 228
  */
229 229
 static int pv_mcd_atomic_helper(struct sip_msg* msg, pv_param_t *param, int op, pv_value_t *val,
230
-		unsigned int (* atomic_ops) (struct memcache *mc, char *key, const size_t key_len,
231
-		const unsigned int val)) {
230
+		memcached_return (* atomic_ops) (memcached_st *mc, const char *key, size_t key_length, uint32_t offset, uint64_t *value)) {
232 231
 
233
-	unsigned int value = 0;
232
+	uint64_t value = 0;
234 233
 	str key;
235
-	struct memcache_req *mcd_req = NULL;
236
-	struct memcache_res *mcd_res = NULL;
234
+	unsigned int expiry = mcd_expire;
235
+	char *return_value;
236
+	uint32_t return_flags;
237
+	memcached_return rc;
237 238
 	
238
-	if (! val->flags&PV_VAL_INT) {
239
+	if (!(val->flags&PV_VAL_INT)) {
239 240
 		LM_ERR("invalid value %.*s for atomic operation, strings not allowed\n",
240 241
 			val->rs.len, val->rs.s);
241 242
 		return -1;
242 243
 	}
243 244
 
244
-	if (pv_mcd_key_check(msg, param, &key) < 0)
245
+	if (pv_mcd_key_check(msg, param, &key, &expiry) < 0)
245 246
 		return -1;
246 247
 
247
-	if (pv_get_mcd_value_helper(msg, &key, &mcd_req, &mcd_res) < 0) {
248
+	if (pv_get_mcd_value_helper(msg, &key, &return_value, &return_flags) < 0) {
248 249
 		return -1;
249 250
 	}
250 251
 
251
-	if(mcd_res->flags&VAR_VAL_STR) {
252
+	if(return_flags&VAR_VAL_STR) {
252 253
 		LM_ERR("could not do atomic operations on string for key %.*s\n", key.len, key.s);
253
-		LM_DBG("free memcache request and result at %p\n", mcd_req);
254
-		mc_req_free(mcd_req);
255 254
 		return -1;
256 255
 	}
257 256
 
258
-	LM_DBG("atomic operation on result %.*s for %d with flag %d\n", mcd_res->bytes, (char*)mcd_res->val, val->ri, mcd_res->flags);
259
-	LM_DBG("free memcache request and result at %p\n", mcd_req);
260
-	mc_req_free(mcd_req);
261
-
262
-	value = atomic_ops(memcached_h, key.s, key.len, val->ri);
263
-	LM_DBG("value from atomic operation %d\n", value);
257
+	if ((rc = atomic_ops(memcached_h, key.s, key.len, val->ri, &value)) != MEMCACHED_SUCCESS) {
258
+		LM_ERR("error performing atomic operation on key %.*s - %s\n", key.len, key.s, memcached_strerror(memcached_h, rc));
259
+		return -1;
260
+	}
264 261
 
265 262
 	return 0;
266 263
 }
... ...
@@ -275,7 +332,7 @@ static int pv_mcd_atomic_helper(struct sip_msg* msg, pv_param_t *param, int op,
275 275
  * \return 0 on success, -1 on failure
276 276
  */
277 277
 int inline pv_inc_mcd_value(struct sip_msg* msg, pv_param_t *param, int op, pv_value_t *val) {
278
-	return pv_mcd_atomic_helper(msg, param, op, val, mc_incr);
278
+	return pv_mcd_atomic_helper(msg, param, op, val, memcached_increment);
279 279
 }
280 280
 
281 281
 
... ...
@@ -288,7 +345,7 @@ int inline pv_inc_mcd_value(struct sip_msg* msg, pv_param_t *param, int op, pv_v
288 288
  * \return 0 on success, -1 on failure
289 289
  */
290 290
 int inline pv_dec_mcd_value(struct sip_msg* msg, pv_param_t *param, int op, pv_value_t *val) {
291
-	return pv_mcd_atomic_helper(msg, param, op, val, mc_decr);
291
+	return pv_mcd_atomic_helper(msg, param, op, val, memcached_decrement);
292 292
 }
293 293
 
294 294
 
... ...
@@ -305,32 +362,30 @@ int inline pv_dec_mcd_value(struct sip_msg* msg, pv_param_t *param, int op, pv_v
305 305
 int pv_set_mcd_expire(struct sip_msg* msg, pv_param_t *param, int op, pv_value_t *val)
306 306
 {
307 307
 	str key;
308
-	struct memcache_req *mcd_req = NULL;
309
-	struct memcache_res *mcd_res = NULL;
308
+	unsigned int expiry = mcd_expire;
309
+        char *return_value;
310
+        uint32_t return_flags;
311
+        memcached_return rc;
310 312
 
311
-	if (! val->flags&PV_VAL_INT) {
313
+	if (!(val->flags&PV_VAL_INT)) {
312 314
 		LM_ERR("invalid value %.*s for expire time, strings not allowed\n",
313 315
 			val->rs.len, val->rs.s);
314 316
 		return -1;
315 317
 	}
316 318
 
317
-	if (pv_mcd_key_check(msg, param, &key) < 0)
319
+	if (pv_mcd_key_check(msg, param, &key, &expiry) < 0)
318 320
 		return -1;
319 321
 
320
-	if (pv_get_mcd_value_helper(msg, &key, &mcd_req, &mcd_res) < 0) {
322
+	if (pv_get_mcd_value_helper(msg, &key, &return_value, &return_flags) < 0) {
321 323
 		return -1;
322 324
 	}
323 325
 
324
-	LM_DBG("set expire time %d on result %.*s for %d with flag %d\n", val->ri, mcd_res->bytes, (char*)mcd_res->val, val->ri, mcd_res->flags);
326
+	LM_DBG("set expire time %d for key %.*s with flag %d\n", val->ri, key.len, key.s, return_flags);
325 327
 
326
-	if (mc_set(memcached_h, key.s, key.len, mcd_res->val, mcd_res->bytes, val->ri, mcd_res->flags) != 0) {
327
-		LM_ERR("could not set expire time %d for key %.*s\n", val->ri, key.len, key.s);
328
-		LM_DBG("free memcache request and result at %p\n", mcd_req);
329
-		mc_req_free(mcd_req);
328
+	if ((rc= memcached_set(memcached_h, key.s, key.len, return_value, strlen(return_value), val->ri, return_flags)) != MEMCACHED_SUCCESS) {
329
+		LM_ERR("could not set expire time %d for key %.*s - error was %s\n", val->ri, key.len, key.s, memcached_strerror(memcached_h, rc));
330 330
 		return -1;
331 331
 	}
332
-	LM_DBG("free memcache request and result at %p\n", mcd_req);
333
-	mc_req_free(mcd_req);
334 332
 
335 333
 	return 0;
336 334
 }
... ...
@@ -1,7 +1,6 @@
1
-/**
2
- * $Id$
3
- *
4
- * Copyright (C) 2009 Henning Westerholt
1
+/*
2
+ * Copyright (C) 2009, 2013 Henning Westerholt
3
+ * Copyright (C) 2013 Charles Chance, sipcentric.com
5 4
  *
6 5
  * This file is part of Kamailio, a free SIP server.
7 6
  *
... ...
@@ -1,7 +1,6 @@
1 1
 /*
2
- * $Id$
3
- *
4
- * Copyright (C) 2009 Henning Westerholt
2
+ * Copyright (C) 2009, 2013 Henning Westerholt
3
+ * Copyright (C) 2013 Charles Chance, sipcentric.com
5 4
  *
6 5
  * This file is part of Kamailio, a free SIP server.
7 6
  *
... ...
@@ -37,23 +36,18 @@
37 37
 MODULE_VERSION
38 38
 
39 39
 
40
-#define DP_ALERT_TEXT    "ALERT:"
41
-#define DP_ERR_TEXT      "ERROR:"
42
-#define DP_WARN_TEXT     "WARNING:"
43
-#define DP_NOTICE_TEXT   "NOTICE:"
44
-#define DP_INFO_TEXT     "INFO:"
45
-
46
-
47 40
 /*! server string */
48
-char* memcached_srv_str = "localhost:11211";
49
-/*! cache expire time in seconds */
50
-unsigned int memcached_expire = 10800;
41
+char* mcd_srv_str = "localhost:11211";
42
+/*! cache (default) expire time in seconds */
43
+unsigned int mcd_expire = 0;
51 44
 /*! cache storage mode, set or add */
52
-unsigned int memcached_mode = 0;
45
+unsigned int mcd_mode = 0;
53 46
 /*! server timeout in ms*/
54
-int memcached_timeout = 5000;
47
+int mcd_timeout = 5000;
55 48
 /*! memcached handle */
56
-struct memcache* memcached_h = NULL;
49
+struct memcached_st *memcached_h;
50
+/*! memcached server list */
51
+struct memcached_server_st *servers;
57 52
 
58 53
 
59 54
 static int mod_init(void);
... ...
@@ -81,10 +75,10 @@ static pv_export_t mod_pvs[] = {
81 81
  * Exported parameters
82 82
  */
83 83
 static param_export_t params[] = {
84
-	{"servers", STR_PARAM, &memcached_srv_str },
85
-	{"expire",   INT_PARAM, &memcached_expire },
86
-	{"timeout", INT_PARAM, &memcached_timeout },
87
-	{"mode",    INT_PARAM, &memcached_mode },
84
+	{"servers", STR_PARAM, &mcd_srv_str },
85
+	{"expire",   INT_PARAM, &mcd_expire },
86
+	{"timeout", INT_PARAM, &mcd_timeout },
87
+	{"mode",    INT_PARAM, &mcd_mode },
88 88
 	{0, 0, 0}
89 89
 };
90 90
 
... ...
@@ -113,7 +107,7 @@ struct module_exports exports = {
113 113
  * \param mem freed memory
114 114
  * \see pkg_free
115 115
  */
116
-static inline void memcached_free(void *mem) {
116
+static inline void mcd_free(void *mem) {
117 117
 	pkg_free(mem);
118 118
 }
119 119
 
... ...
@@ -124,7 +118,7 @@ static inline void memcached_free(void *mem) {
124 124
  * \return allocated memory, or NULL on failure
125 125
  * \see pkg_malloc
126 126
  */
127
-static inline void* memcached_malloc(const size_t size) {
127
+static inline void* mcd_malloc(const size_t size) {
128 128
 	return pkg_malloc(size);
129 129
 }
130 130
 
... ...
@@ -136,69 +130,10 @@ static inline void* memcached_malloc(const size_t size) {
136 136
  * \return allocated memory, or NULL on failure
137 137
  * \see pkg_realloc
138 138
  */
139
-static inline void* memcached_realloc(void *mem, const size_t size) {
139
+static inline void* mcd_realloc(void *mem, const size_t size) {
140 140
  	return pkg_realloc(mem, size);
141 141
 }
142 142
 
143
-
144
-/*!
145
- * \brief Small wrapper around our internal logging function
146
- */
147
-static int memcache_err_func(MCM_ERR_FUNC_ARGS) {
148
-
149
-	const struct memcache_ctxt *ctxt;
150
-	struct memcache_err_ctxt *ectxt;
151
-	int error_level;
152
-	const char * error_str;
153
-
154
-	MCM_ERR_INIT_CTXT(ctxt, ectxt);
155
-
156
-	switch (ectxt->severity) {
157
-		case MCM_ERR_LVL_INFO:
158
-			error_level = L_INFO;
159
-			error_str = DP_INFO_TEXT;
160
-			break;
161
-		case MCM_ERR_LVL_NOTICE:
162
-			error_level = L_NOTICE;
163
-			error_str = DP_NOTICE_TEXT;
164
-			break;
165
-		case MCM_ERR_LVL_WARN:
166
-			error_level = L_WARN;
167
-			error_str = DP_WARN_TEXT;
168
-			break;
169
-		case MCM_ERR_LVL_ERR:
170
-			error_level = L_ERR;
171
-			error_str  = DP_ERR_TEXT;
172
-			/* try to continue */
173
- 			ectxt->cont = 'y';
174
-			break;
175
-		case MCM_ERR_LVL_FATAL:
176
-  		default:
177
-			error_level = L_ALERT;
178
-			error_str = DP_ALERT_TEXT;
179
-			ectxt->cont = 'y';
180
-			break;
181
-	}
182
-
183
-	/*
184
-	* ectxt->errmsg - per error message passed along via one of the MCM_*_MSG() macros (optional)
185
-	* ectxt->errstr - memcache error string (optional, though almost always set)
186
-	*/
187
-	if (ectxt->errstr != NULL && ectxt->errmsg != NULL)
188
-		LM_GEN1(error_level, "%s memcached: %s():%u: %s: %.*s\n", error_str, ectxt->funcname, ectxt->lineno, ectxt->errstr,
189
-			(int)ectxt->errlen, ectxt->errmsg);
190
-	else if (ectxt->errstr == NULL && ectxt->errmsg != NULL)
191
-		LM_GEN1(error_level, "%s memcached: %s():%u: %.*s\n", error_str, ectxt->funcname, ectxt->lineno, (int)ectxt->errlen,
192
-			ectxt->errmsg);
193
-	else if (ectxt->errstr != NULL && ectxt->errmsg == NULL)
194
-		LM_GEN1(error_level, "%s memcached: %s():%u: %s\n", error_str, ectxt->funcname, ectxt->lineno, ectxt->errstr);
195
-	else
196
-		LM_GEN1(error_level, "%s memcached: %s():%u\n", error_str, ectxt->funcname, ectxt->lineno);
197
-
198
-	return 0;
199
-}
200
-
201
-
202 143
 /*!
203 144
  * \brief Module initialization function
204 145
  * \return 0 on success, -1 on failure
... ...
@@ -206,58 +141,90 @@ static int memcache_err_func(MCM_ERR_FUNC_ARGS) {
206 206
 static int mod_init(void) {
207 207
 	char *server, *port;
208 208
 	unsigned int len = 0;
209
+	memcached_return rc;
209 210
 
210
-	/* setup the callbacks to our internal memory manager */
211
-	if (mcMemSetup(memcached_free, memcached_malloc,
212
-			memcached_malloc, memcached_realloc) != 0) {
213
-		LM_ERR("could not setup memory management callbacks\n");
214
-		return -1;
215
-	}
216
-
217
-	if (mcErrSetup(memcache_err_func) != 0) {
218
-		LM_ERR("could not setup error handler callback\n");
219
-		return -1;
220
-	}
221
-
222
-	/*! delete eventual log filters */
223
-	mc_err_filter_del(MCM_ERR_LVL_INFO);
224
-	mc_err_filter_del(MCM_ERR_LVL_NOTICE);
225
-
226
-	memcached_h = mc_new();
227
-	if (memcached_h == NULL) {
228
-		PKG_MEM_ERROR;
229
-		return -1;
230
-	}
231
-	
232
-	if ((port = strchr(memcached_srv_str, ':')) != NULL) {
211
+	if ((port = strchr(mcd_srv_str, ':')) != NULL) {
233 212
 		port = port + 1;
234
-		len = strlen(memcached_srv_str) - strlen(port) - 1;
213
+		len = strlen(mcd_srv_str) - strlen(port) - 1;
235 214
 	} else {
236 215
 		LM_DBG("no port definition, using default port\n");
237 216
 		port = "11211";
238
-		len = strlen(memcached_srv_str) ;
217
+		len = strlen(mcd_srv_str) ;
239 218
 	}
240 219
 	
241
-
242 220
 	server = pkg_malloc(len);
243 221
 	if (server == NULL) {
244 222
 		PKG_MEM_ERROR;
245 223
 		return -1;
246 224
 	}
247 225
 
248
-	strncpy(server, memcached_srv_str, len);
226
+	strncpy(server, mcd_srv_str, len);
249 227
 	server[len] = '\0';
250 228
 
251
-	mc_timeout(memcached_h, 0, memcached_timeout);
229
+        servers = memcached_server_list_append(servers, server, atoi(port), &rc);
252 230
 
253
-	if (mc_server_add(memcached_h, server, port) != 0) {
254
-		LM_ERR("could not add server %s:%s\n", server, port);
231
+	memcached_h = memcached_create(NULL);
232
+	if (memcached_h == NULL) {
233
+		LM_ERR("could not create memcached structure\n");
234
+		return -1;
235
+	}
236
+	LM_DBG("allocated new server handle at %p", memcached_h);
237
+	
238
+	#ifdef MEMCACHED_ENABLE_DEPRECATED
239
+	/** 
240
+	 * \note Set callbacks to our internal memory manager
241
+	 * \bug this don't work for now
242
+	 * \todo Move to new memcached_set_memory_allocators function, this deprecated since 0.32
243
+	 * 
244
+	 * MEMCACHED_CALLBACK_MALLOC_FUNCTION
245
+	 * This alllows yout to pass in a customized version of malloc that
246
+	 * will be used instead of the builtin malloc(3) call. The prototype
247
+	 * for this is:
248
+	 * void *(*memcached_malloc_function)(memcached_st *ptr, const size_t size);
249
+	 * 
250
+	 * MEMCACHED_CALLBACK_REALLOC_FUNCTION
251
+	 * This alllows yout to pass in a customized version of realloc that
252
+	 * will be used instead of the builtin realloc(3) call. The prototype
253
+	 * for this is:
254
+	 * void *(*memcached_realloc_function)(memcached_st *ptr, void *mem, const size_t size);
255
+	 * 
256
+	 * MEMCACHED_CALLBACK_FREE_FUNCTION
257
+	 * This alllows yout to pass in a customized version of realloc that
258
+	 * will be used instead of the builtin free(3) call. The prototype
259
+	 * for this is:
260
+	 * typedef void (*memcached_free_function)(memcached_st *ptr, void *mem);
261
+	 */
262
+	LM_DBG("set memory manager callbacks");	
263
+	if (memcached_callback_set(memcached_h, MEMCACHED_CALLBACK_MALLOC_FUNCTION, mcd_free) != MEMCACHED_SUCCESS) {
264
+		LM_ERR("could not set malloc callback handler");
265
+		return -1;
266
+	}
267
+	if (memcached_callback_set(memcached_h, MEMCACHED_CALLBACK_REALLOC_FUNCTION, mcd_realloc) != MEMCACHED_SUCCESS) {
268
+		LM_ERR("could not set realloc callback handler");
269
+		return -1;
270
+	}
271
+	if (memcached_callback_set(memcached_h, MEMCACHED_CALLBACK_FREE_FUNCTION, mcd_free) != MEMCACHED_SUCCESS) {
272
+		LM_ERR("could not set free callback handler");
273
+		return -1;
274
+	}
275
+	LM_DBG("memory manager callbacks set");
276
+	#endif
277
+	
278
+	if (memcached_behavior_set(memcached_h, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, mcd_timeout) != MEMCACHED_SUCCESS) {
279
+		LM_ERR("could not set server connection timeout");
280
+		return -1;
281
+	}
282
+	rc = memcached_server_push(memcached_h, servers);
283
+	if (rc == MEMCACHED_SUCCESS) {
284
+		LM_DBG("added server list to structure\n");
285
+	} else {
286
+		LM_ERR("attempt to add server list to structure returned %s.\n", memcached_strerror(memcached_h, rc));
255 287
 		return -1;
256 288
 	}
257
-	LM_INFO("connected to server %s:%s\n", server, port);
258
-	pkg_free(server);
259 289
 
260
-	LM_INFO("memcached client version is %s, released on %d\n", mc_version(), mc_reldate());
290
+	pkg_free(server);
291
+	
292
+	LM_INFO("libmemcached version is %s\n", memcached_lib_version());
261 293
 	return 0;
262 294
 }
263 295
 
... ...
@@ -267,8 +234,7 @@ static int mod_init(void) {
267 267
  */
268 268
 static void mod_destroy(void) {
269 269
 	if (memcached_h != NULL)
270
-		mc_server_disconnect_all(memcached_h);
271
-
272
-	if (memcached_h != NULL)
273
-		mc_free(memcached_h);
270
+		memcached_free(memcached_h);
271
+	if (servers != NULL)
272
+		memcached_server_list_free(servers);
274 273
 }
... ...
@@ -1,7 +1,6 @@
1 1
 /*
2
- * $Id$
3
- *
4
- * Copyright (C) 2009 Henning Westerholt
2
+ * Copyright (C) 2009, 2013 Henning Westerholt
3
+ * Copyright (C) 2013 Charles Chance, sipcentric.com
5 4
  *
6 5
  * This file is part of Kamailio, a free SIP server.
7 6
  *
... ...
@@ -24,21 +23,22 @@
24 24
  * \brief memcached module
25 25
  */
26 26
 
27
-#include <memcache.h>
27
+#include <libmemcached/memcached.h>
28 28
 
29 29
 #ifndef MEMCACHED_H
30 30
 #define MEMCACHED_H
31 31
 
32 32
 /*! server string */
33
-extern char* db_memcached_srv_str;
33
+extern char* mcd_srv_str;
34 34
 /*! cache expire time in seconds */
35
-extern unsigned int memcached_expire;
35
+extern unsigned int mcd_expire;
36 36
 /*! cache storage mode, set or add */
37
-extern unsigned int memcached_mode;
37
+extern unsigned int mcd_mode;
38 38
 /*! server timeout */
39
-extern int memcached_timeout;
39
+extern int mcd_timeout;
40 40
 /*! memcached handle */
41
-extern struct memcache* memcached_h;
42
-
41
+extern struct memcached_st* memcached_h;
42
+/*! memcached server list */
43
+extern struct memcached_server_st *servers;
43 44
 
44 45
 #endif