瀏覽代碼

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
Daniel-Constantin Mierla 14 年之前
父節點
當前提交
116fceb0da
共有 5 個文件被更改,包括 166 次插入1 次删除
  1. 107 0
      modules_k/htable/ht_api.c
  2. 2 0
      modules_k/htable/ht_api.h
  3. 49 0
      modules_k/htable/ht_var.c
  4. 4 1
      modules_k/htable/ht_var.h
  5. 4 0
      modules_k/htable/htable.c

+ 107 - 0
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;

+ 2 - 0
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);

+ 49 - 0
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);
+}

+ 4 - 1
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

+ 4 - 0
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 }
 };