Module: sip-router Branch: master Commit: 116fceb0da9768e9e146e6d90dc3b36630475329 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=116fceb0...
Author: Daniel-Constantin Mierla miconda@gmail.com Committer: Daniel-Constantin Mierla miconda@gmail.com Date: Sat Apr 30 19:50:32 2011 +0200
htable: added two new PVs
- $shtinc(htable=>key) - add atomically 1 to the value of the item - $shtdec(htable=>key) - decrement atomically 1 to the value of the item - both return the new value of the item - they work only with items having iteger values
---
modules_k/htable/ht_api.c | 107 +++++++++++++++++++++++++++++++++++++++++++++ modules_k/htable/ht_api.h | 2 + modules_k/htable/ht_var.c | 49 ++++++++++++++++++++ modules_k/htable/ht_var.h | 5 ++- modules_k/htable/htable.c | 4 ++ 5 files changed, 166 insertions(+), 1 deletions(-)
diff --git a/modules_k/htable/ht_api.c b/modules_k/htable/ht_api.c index 23bc59e..da473e6 100644 --- a/modules_k/htable/ht_api.c +++ b/modules_k/htable/ht_api.c @@ -516,6 +516,113 @@ int ht_del_cell(ht_t *ht, str *name) return 0; }
+ht_cell_t* ht_cell_value_add(ht_t *ht, str *name, int val, int mode, + ht_cell_t *old) +{ + unsigned int idx; + unsigned int hid; + ht_cell_t *it, *prev, *cell; + time_t now; + int_str isval; + + if(ht==NULL || ht->entries==NULL) + return NULL; + + hid = ht_compute_hash(name); + + idx = ht_get_entry(hid, ht->htsize); + + now = 0; + if(ht->htexpire>0) + now = time(NULL); + prev = NULL; + if(mode) lock_get(&ht->entries[idx].lock); + it = ht->entries[idx].first; + while(it!=NULL && it->cellid < hid) + { + prev = it; + it = it->next; + } + while(it!=NULL && it->cellid == hid) + { + if(name->len==it->name.len + && strncmp(name->s, it->name.s, name->len)==0) + { + /* update value */ + if(it->flags&AVP_VAL_STR) + { + /* string value cannot be incremented */ + if(mode) lock_release(&ht->entries[idx].lock); + return NULL; + } else { + it->value.n += val; + it->expire = now + ht->htexpire; + if(old!=NULL) + { + if(old->msize>=it->msize) + { + memcpy(old, it, it->msize); + lock_release(&ht->entries[idx].lock); + return old; + } + } + cell = (ht_cell_t*)pkg_malloc(it->msize); + if(cell!=NULL) + memcpy(cell, it, it->msize); + + if(mode) lock_release(&ht->entries[idx].lock); + return cell; + } + } + prev = it; + it = it->next; + } + /* add val if htable has an integer init value */ + if(ht->flags!=PV_VAL_INT) + return NULL; + isval.n = ht->initval.n + val; + it = ht_cell_new(name, 0, &isval, hid); + if(it == NULL) + { + LM_ERR("cannot create new cell.\n"); + if(mode) lock_release(&ht->entries[idx].lock); + return NULL; + } + it->expire = now + ht->htexpire; + if(prev==NULL) + { + if(ht->entries[idx].first!=NULL) + { + it->next = ht->entries[idx].first; + ht->entries[idx].first->prev = it; + } + ht->entries[idx].first = it; + } else { + it->next = prev->next; + it->prev = prev; + if(prev->next) + prev->next->prev = it; + prev->next = it; + } + ht->entries[idx].esize++; + if(old!=NULL) + { + if(old->msize>=it->msize) + { + memcpy(old, it, it->msize); + lock_release(&ht->entries[idx].lock); + return old; + } + } + cell = (ht_cell_t*)pkg_malloc(it->msize); + if(cell!=NULL) + memcpy(cell, it, it->msize); + + if(mode) lock_release(&ht->entries[idx].lock); + return cell; +} + + ht_cell_t* ht_cell_pkg_copy(ht_t *ht, str *name, ht_cell_t *old) { unsigned int idx; diff --git a/modules_k/htable/ht_api.h b/modules_k/htable/ht_api.h index 6a92f29..831267e 100644 --- a/modules_k/htable/ht_api.h +++ b/modules_k/htable/ht_api.h @@ -74,6 +74,8 @@ int ht_init_tables(void); int ht_destroy(void); int ht_set_cell(ht_t *ht, str *name, int type, int_str *val, int mode); int ht_del_cell(ht_t *ht, str *name); +ht_cell_t* ht_cell_value_add(ht_t *ht, str *name, int val, int mode, + ht_cell_t *old);
int ht_dbg(void); ht_cell_t* ht_cell_pkg_copy(ht_t *ht, str *name, ht_cell_t *old); diff --git a/modules_k/htable/ht_var.c b/modules_k/htable/ht_var.c index 0d52254..627e70b 100644 --- a/modules_k/htable/ht_var.c +++ b/modules_k/htable/ht_var.c @@ -292,3 +292,52 @@ int pv_get_ht_cv(struct sip_msg *msg, pv_param_t *param, return pv_get_sintval(msg, param, res, cnt); }
+int pv_get_ht_add(struct sip_msg *msg, pv_param_t *param, + pv_value_t *res, int val) +{ + str htname; + ht_cell_t *htc=NULL; + ht_pv_t *hpv; + + hpv = (ht_pv_t*)param->pvn.u.dname; + + if(hpv->ht==NULL) + { + hpv->ht = ht_get_table(&hpv->htname); + if(hpv->ht==NULL) + return pv_get_null(msg, param, res); + } + if(pv_printf_s(msg, hpv->pve, &htname)!=0) + { + LM_ERR("cannot get $ht name\n"); + return -1; + } + htc = ht_cell_value_add(hpv->ht, &htname, val, 1, _htc_local); + if(htc==NULL) + { + return pv_get_null(msg, param, res); + } + if(_htc_local!=htc) + { + ht_cell_pkg_free(_htc_local); + _htc_local=htc; + } + + if(htc->flags&AVP_VAL_STR) + return pv_get_null(msg, param, res); + + /* integer */ + return pv_get_sintval(msg, param, res, htc->value.n); +} + +int pv_get_ht_inc(struct sip_msg *msg, pv_param_t *param, + pv_value_t *res) +{ + return pv_get_ht_add(msg, param, res, 1); +} + +int pv_get_ht_dec(struct sip_msg *msg, pv_param_t *param, + pv_value_t *res) +{ + return pv_get_ht_add(msg, param, res, -1); +} diff --git a/modules_k/htable/ht_var.h b/modules_k/htable/ht_var.h index e6856b2..4ee895f 100644 --- a/modules_k/htable/ht_var.h +++ b/modules_k/htable/ht_var.h @@ -38,6 +38,9 @@ int pv_get_ht_cn(struct sip_msg *msg, pv_param_t *param, pv_value_t *res); int pv_get_ht_cv(struct sip_msg *msg, pv_param_t *param, pv_value_t *res); - +int pv_get_ht_inc(struct sip_msg *msg, pv_param_t *param, + pv_value_t *res); +int pv_get_ht_dec(struct sip_msg *msg, pv_param_t *param, + pv_value_t *res);
#endif diff --git a/modules_k/htable/htable.c b/modules_k/htable/htable.c index 461817f..7d387cc 100644 --- a/modules_k/htable/htable.c +++ b/modules_k/htable/htable.c @@ -76,6 +76,10 @@ static pv_export_t mod_pvs[] = { pv_parse_ht_name, 0, 0, 0 }, { {"shtcv", sizeof("shtcv")-1}, PVT_OTHER, pv_get_ht_cv, 0, pv_parse_ht_name, 0, 0, 0 }, + { {"shtinc", sizeof("shtinc")-1}, PVT_OTHER, pv_get_ht_inc, 0, + pv_parse_ht_name, 0, 0, 0 }, + { {"shtdec", sizeof("shtdec")-1}, PVT_OTHER, pv_get_ht_dec, 0, + pv_parse_ht_name, 0, 0, 0 }, { {0, 0}, 0, 0, 0, 0, 0, 0, 0 } };