00001
00027 #include "mcd_var.h"
00028
00029 #include "memcached.h"
00030 #include "../../ut.h"
00031 #include "../../mem/mem.h"
00032 #include "../pv/pv_svar.h"
00033 #include "../../md5utils.h"
00034
00035
00043 static inline int pv_mcd_key_check(struct sip_msg *msg, pv_param_t *param, str * out) {
00044
00045 str tmp;
00046 static char hash[32];
00047
00048 if (msg == NULL || param == NULL) {
00049 LM_ERR("bad parameters\n");
00050 return -1;
00051 }
00052
00053 if (pv_printf_s(msg, param->pvn.u.dname, &tmp) != 0)
00054 {
00055 LM_ERR("cannot get key name\n");
00056 return -1;
00057 }
00058
00059 if (tmp.len < 250) {
00060 out->s = tmp.s;
00061 out->len = tmp.len;
00062 } else {
00063 LM_DBG("key too long (%d), hash it\n", tmp.len);
00064 MD5StringArray (hash, &tmp, 1);
00065 out->s = hash;
00066 out->len = 32;
00067 }
00068 return 0;
00069 }
00070
00079 static int pv_get_mcd_value_helper(struct sip_msg *msg, str *key,
00080 struct memcache_req **mcd_req, struct memcache_res **mcd_res) {
00081
00082
00083 if ( (*mcd_req = mc_req_new()) == NULL) {
00084 PKG_MEM_ERROR;
00085 return -1;
00086 }
00087 LM_DBG("allocate new memcache request at %p\n", *mcd_req);
00088
00089 if ( (*mcd_res = mc_req_add(*mcd_req, key->s, key->len)) == NULL) {
00090 PKG_MEM_ERROR;
00091 return -1;
00092 }
00093 LM_DBG("allocate new memcache result at %p\n", *mcd_res);
00094
00095 mc_get(memcached_h, *mcd_req);
00096 if (! ( (*mcd_res)->_flags & MCM_RES_FOUND)) {
00097 LM_ERR("could not get result for key %.*s\n", key->len, key->s);
00098 LM_DBG("free memcache request and result at %p\n", mcd_req);
00099 mc_req_free(*mcd_req);
00100 return -1;
00101 }
00102 LM_DBG("result: %.*s for key %.*s with flag %d\n", (*mcd_res)->bytes, (char*)(*mcd_res)->val,
00103 key->len, key->s, (*mcd_res)->flags);
00104
00105 return 0;
00106 }
00107
00115 int pv_get_mcd_value(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) {
00116
00117 unsigned int res_int = 0;
00118 str key, res_str;
00119 struct memcache_req *mcd_req = NULL;
00120 struct memcache_res *mcd_res = NULL;
00121
00122 if (pv_mcd_key_check(msg, param, &key) < 0) {
00123 return pv_get_null(msg, param, res);
00124 }
00125
00126 if (res==NULL)
00127 return pv_get_null(msg, param, res);
00128
00129 if (pv_get_mcd_value_helper(msg, &key, &mcd_req, &mcd_res) < 0) {
00130 return pv_get_null(msg, param, res);
00131 }
00132
00133 res_str.len = mcd_res->bytes;
00134 res_str.s = mcd_res->val;
00135
00136 trim_len(res_str.len, res_str.s, res_str);
00137
00138 if(mcd_res->flags&VAR_VAL_STR) {
00139 if (pkg_str_dup(&(res->rs), &res_str) < 0) {
00140 LM_ERR("could not copy string\n");
00141 goto errout;
00142 }
00143 res->flags = PV_VAL_STR;
00144 } else {
00145 if (str2int(&res_str, &res_int) < 0) {
00146 LM_ERR("could not convert string %.*s to integer value\n", res_str.len, res_str.s);
00147 goto errout;
00148 }
00149 res->rs = res_str;
00150 res->ri = res_int;
00151 res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
00152 }
00153 LM_DBG("free memcache request and result at %p\n", mcd_req);
00154 mc_req_free(mcd_req);
00155
00156 return 0;
00157
00158 errout:
00159 LM_DBG("free memcache request and result at %p\n", mcd_req);
00160 mc_req_free(mcd_req);
00161 return pv_get_null(msg, param, res);
00162 }
00163
00164
00175 int pv_set_mcd_value(struct sip_msg* msg, pv_param_t *param, int op, pv_value_t *val) {
00176
00177 unsigned int val_flag = 0;
00178 str val_str, key;
00179
00180 if (pv_mcd_key_check(msg, param, &key) < 0)
00181 return -1;
00182
00183 if (val == NULL) {
00184 if (mc_delete(memcached_h, key.s, key.len, 0) != 0) {
00185 LM_ERR("could not delete key %.*s\n", param->pvn.u.isname.name.s.len,
00186 param->pvn.u.isname.name.s.s);
00187 }
00188 LM_DBG("delete key %.*s\n", key.len, key.s);
00189 return 0;
00190 }
00191
00192 if (val->flags&PV_VAL_INT) {
00193 val_str.s = int2str(val->ri, &val_str.len);
00194 } else {
00195 val_str = val->rs;
00196 val_flag = VAR_VAL_STR;
00197 }
00198
00199 if (memcached_mode == 0) {
00200 if (mc_set(memcached_h, key.s, key.len, val_str.s, val_str.len, memcached_expire, val_flag) != 0) {
00201 LM_ERR("could not set value for key %.*s\n", key.len, key.s);
00202 return -1;
00203 }
00204 } else {
00205 if (mc_add(memcached_h, key.s, key.len, val_str.s, val_str.len, memcached_expire, val_flag) != 0) {
00206 LM_ERR("could not add value for key %.*s\n", key.len, key.s);
00207 return -1;
00208 }
00209 }
00210 LM_DBG("set value %.*s for key %.*s with flag %d\n", val_str.len, val_str.s, key.len, key.s, val_flag);
00211
00212 return 0;
00213 }
00214
00215
00229 static int pv_mcd_atomic_helper(struct sip_msg* msg, pv_param_t *param, int op, pv_value_t *val,
00230 unsigned int (* atomic_ops) (struct memcache *mc, char *key, const size_t key_len,
00231 const unsigned int val)) {
00232
00233 unsigned int value = 0;
00234 str key;
00235 struct memcache_req *mcd_req = NULL;
00236 struct memcache_res *mcd_res = NULL;
00237
00238 if (! val->flags&PV_VAL_INT) {
00239 LM_ERR("invalid value %.*s for atomic operation, strings not allowed\n",
00240 val->rs.len, val->rs.s);
00241 return -1;
00242 }
00243
00244 if (pv_mcd_key_check(msg, param, &key) < 0)
00245 return -1;
00246
00247 if (pv_get_mcd_value_helper(msg, &key, &mcd_req, &mcd_res) < 0) {
00248 return -1;
00249 }
00250
00251 if(mcd_res->flags&VAR_VAL_STR) {
00252 LM_ERR("could not do atomic operations on string for key %.*s\n", key.len, key.s);
00253 LM_DBG("free memcache request and result at %p\n", mcd_req);
00254 mc_req_free(mcd_req);
00255 return -1;
00256 }
00257
00258 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);
00259 LM_DBG("free memcache request and result at %p\n", mcd_req);
00260 mc_req_free(mcd_req);
00261
00262 value = atomic_ops(memcached_h, key.s, key.len, val->ri);
00263 LM_DBG("value from atomic operation %d\n", value);
00264
00265 return 0;
00266 }
00267
00268
00277 int inline pv_inc_mcd_value(struct sip_msg* msg, pv_param_t *param, int op, pv_value_t *val) {
00278 return pv_mcd_atomic_helper(msg, param, op, val, mc_incr);
00279 }
00280
00281
00290 int inline pv_dec_mcd_value(struct sip_msg* msg, pv_param_t *param, int op, pv_value_t *val) {
00291 return pv_mcd_atomic_helper(msg, param, op, val, mc_decr);
00292 }
00293
00294
00305 int pv_set_mcd_expire(struct sip_msg* msg, pv_param_t *param, int op, pv_value_t *val)
00306 {
00307 str key;
00308 struct memcache_req *mcd_req = NULL;
00309 struct memcache_res *mcd_res = NULL;
00310
00311 if (! val->flags&PV_VAL_INT) {
00312 LM_ERR("invalid value %.*s for expire time, strings not allowed\n",
00313 val->rs.len, val->rs.s);
00314 return -1;
00315 }
00316
00317 if (pv_mcd_key_check(msg, param, &key) < 0)
00318 return -1;
00319
00320 if (pv_get_mcd_value_helper(msg, &key, &mcd_req, &mcd_res) < 0) {
00321 return -1;
00322 }
00323
00324 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);
00325
00326 if (mc_set(memcached_h, key.s, key.len, mcd_res->val, mcd_res->bytes, val->ri, mcd_res->flags) != 0) {
00327 LM_ERR("could not set expire time %d for key %.*s\n", val->ri, key.len, key.s);
00328 LM_DBG("free memcache request and result at %p\n", mcd_req);
00329 mc_req_free(mcd_req);
00330 return -1;
00331 }
00332 LM_DBG("free memcache request and result at %p\n", mcd_req);
00333 mc_req_free(mcd_req);
00334
00335 return 0;
00336 }
00337
00338
00345 int pv_parse_mcd_name(pv_spec_p sp, str *in) {
00346
00347 pv_elem_t * tmp = NULL;
00348
00349 if(sp==NULL || in==NULL || in->len<=0)
00350 return -1;
00351
00352
00353 tmp = pkg_malloc(sizeof(pv_elem_t));
00354 if (tmp == NULL) {
00355 PKG_MEM_ERROR;
00356 return -1;
00357 }
00358 memset(tmp, 0, sizeof(pv_elem_t));
00359
00360 if(pv_parse_format(in, &tmp) || tmp==NULL) {
00361 LM_ERR("wrong format [%.*s]\n", in->len, in->s);
00362 return -1;
00363 }
00364
00365 sp->pvp.pvn.u.dname = tmp;
00366 sp->pvp.pvn.type = PV_NAME_PVAR;
00367
00368 return 0;
00369 }