Module: sip-router
Branch: master
Commit: 116fceb0da9768e9e146e6d90dc3b36630475329
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=116fceb…
Author: Daniel-Constantin Mierla <miconda(a)gmail.com>
Committer: Daniel-Constantin Mierla <miconda(a)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 }
};