Example #1
0
int ht_iterator_next(str *iname)
{
	int i;
	int k;

	k = -1;
	for(i=0; i<HT_ITERATOR_SIZE; i++)
	{
		if(_ht_iterators[i].name.len>0)
		{
			if(_ht_iterators[i].name.len==iname->len
					&& strncmp(_ht_iterators[i].name.s, iname->s, iname->len)==0)
			{
				k = i;
				break;
			}
		} else {
			if(k==-1) k = i;
		}
	}
	if(k==-1)
	{
		LM_ERR("iterator not found [%.*s]\n", iname->len, iname->s);
		return -1;
	}
	if(_ht_iterators[k].ht==NULL)
	{
		LM_ERR("iterator not initialized [%.*s]\n", iname->len, iname->s);
		return -1;
	}
	if(_ht_iterators[k].it==NULL)
	{
		/* first execution - start from first slot */
		_ht_iterators[k].slot=0;
	} else {
		_ht_iterators[k].it = _ht_iterators[k].it->next;
		if(_ht_iterators[k].it!=NULL)
		{
			/* next item is in the same slot */
			return 0;
		}
		/* next is not in the same slot - release and try next one */
		_ht_iterators[k].it = NULL;
		ht_slot_unlock(_ht_iterators[k].ht, _ht_iterators[k].slot);
		_ht_iterators[k].slot++;
	}

	for( ; _ht_iterators[k].slot<_ht_iterators[k].ht->htsize; _ht_iterators[k].slot++)
	{
		ht_slot_lock(_ht_iterators[k].ht, _ht_iterators[k].slot);
		if(_ht_iterators[k].ht->entries[_ht_iterators[k].slot].first!=NULL)
		{
			_ht_iterators[k].it = _ht_iterators[k].ht->entries[_ht_iterators[k].slot].first;
			return 0;
		}
		ht_slot_unlock(_ht_iterators[k].ht, _ht_iterators[k].slot);
	}
	return -1;
}
Example #2
0
ht_cell_t* ht_cell_pkg_copy(ht_t *ht, str *name, ht_cell_t *old)
{
	unsigned int idx;
	unsigned int hid;
	ht_cell_t *it, *cell;

	if(ht==NULL || ht->entries==NULL)
		return NULL;

	hid = ht_compute_hash(name);

	idx = ht_get_entry(hid, ht->htsize);

	/* head test and return */
	if(ht->entries[idx].first==NULL)
		return NULL;

	ht_slot_lock(ht, idx);
	it = ht->entries[idx].first;
	while(it!=NULL && it->cellid < hid)
		it = it->next;
	while(it!=NULL && it->cellid == hid)
	{
		if(name->len==it->name.len
				&& strncmp(name->s, it->name.s, name->len)==0)
		{
			/* found */
			if(ht->htexpire>0 && it->expire!=0 && it->expire<time(NULL)) {
				/* entry has expired, return NULL */
				ht_slot_unlock(ht, idx);
				return NULL;
			}
			if(old!=NULL)
			{
				if(old->msize>=it->msize)
				{
					memcpy(old, it, it->msize);
					ht_slot_unlock(ht, idx);
					return old;
				}
			}
			cell = (ht_cell_t*)pkg_malloc(it->msize);
			if(cell!=NULL)
				memcpy(cell, it, it->msize);
			ht_slot_unlock(ht, idx);
			return cell;
		}
		it = it->next;
	}
	ht_slot_unlock(ht, idx);
	return NULL;
}
Example #3
0
int ht_dbg(void)
{
	int i;
	ht_cell_t *it;
	ht_t *ht;

	ht = _ht_root;
	while(ht)
	{
		LM_ERR("===== htable[%.*s] hid: %u exp: %u>\n", ht->name.len,
				ht->name.s, ht->htid, ht->htexpire);
		for(i=0; i<ht->htsize; i++)
		{
			ht_slot_lock(ht, i);
			LM_ERR("htable[%d] -- <%d>\n", i, ht->entries[i].esize);
			it = ht->entries[i].first;
			while(it)
			{
				LM_ERR("\tcell: %.*s\n", it->name.len, it->name.s);
				LM_ERR("\thid: %u msize: %u flags: %d expire: %u\n", it->cellid,
						it->msize, it->flags, (unsigned int)it->expire);
				if(it->flags&AVP_VAL_STR)
					LM_ERR("\tv-s:%.*s\n", it->value.s.len, it->value.s.s);
				else
					LM_ERR("\tv-i:%d\n", it->value.n);
				it = it->next;
			}
			ht_slot_unlock(ht, i);
		}
		ht = ht->next;
	}
	return 0;
}
Example #4
0
int ht_reset_content(ht_t *ht)
{
	ht_cell_t *it;
	ht_cell_t *it0;
	int i;

	if(ht==NULL)
		return -1;

	for(i=0; i<ht->htsize; i++)
	{
		/* free entries */
		ht_slot_lock(ht, i);
		it = ht->entries[i].first;
		while(it)
		{
			it0 = it->next;
			if(it->prev==NULL)
				ht->entries[i].first = it->next;
			else
				it->prev->next = it->next;
			if(it->next)
				it->next->prev = it->prev;
			ht->entries[i].esize--;
			ht_cell_free(it);
			it = it0;
		}
		ht_slot_unlock(ht, i);
	}
	return 0;
}
Example #5
0
static int ki_ht_slot_xlock(sip_msg_t *msg, str *htname, str *skey, int lmode)
{
	ht_t *ht;
	unsigned int hid;
	unsigned int idx;

	ht = ht_get_table(htname);
	if(ht==NULL) {
		LM_ERR("cannot get hash table by name [%.*s] (%d)\n",
				htname->len, htname->s, lmode);
		return -1;
	}

	hid = ht_compute_hash(skey);

	idx = ht_get_entry(hid, ht->htsize);

	if(lmode==0) {
		LM_DBG("locking slot %.*s[%u] for key %.*s\n",
				htname->len, htname->s,
				idx, skey->len, skey->s);
		ht_slot_lock(ht, idx);
	} else {
		LM_DBG("unlocking slot %.*s[%u] for key %.*s\n",
				htname->len, htname->s,
				idx, skey->len, skey->s);
		ht_slot_unlock(ht, idx);
	}
	return 1;
}
Example #6
0
int ht_iterator_end(str *iname)
{
	int i;

	for(i=0; i<HT_ITERATOR_SIZE; i++)
	{
		if(_ht_iterators[i].name.len>0)
		{
			if(_ht_iterators[i].name.len==iname->len
					&& strncmp(_ht_iterators[i].name.s, iname->s, iname->len)==0)
			{
				if(_ht_iterators[i].ht!=NULL && _ht_iterators[i].it!=NULL)
				{
					if(_ht_iterators[i].slot>=0 && _ht_iterators[i].slot<_ht_iterators[i].ht->htsize)
					{
						ht_slot_unlock(_ht_iterators[i].ht, _ht_iterators[i].slot);
					}
				}
				memset(&_ht_iterators[i], 0, sizeof(ht_iterator_t));
				return 0;
			}
		}
	}

	return -1;
}
Example #7
0
int ht_set_cell_expire(ht_t *ht, str *name, int type, int_str *val)
{
	unsigned int idx;
	unsigned int hid;
	ht_cell_t *it;
	time_t now;

	if(ht==NULL || ht->entries==NULL)
		return -1;

	/* str value - ignore */
	if(type&AVP_VAL_STR)
		return 0;
	/* not auto-expire htable */
	if(ht->htexpire==0)
		return 0;

	hid = ht_compute_hash(name);

	idx = ht_get_entry(hid, ht->htsize);

	now = 0;
	if(val->n>0)
		now = time(NULL) + val->n;
	LM_DBG("set auto-expire to %u (%d)\n", (unsigned int)now,
			val->n);

	ht_slot_lock(ht, idx);
	it = ht->entries[idx].first;
	while(it!=NULL && it->cellid < hid)
		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 */
			it->expire = now;
			ht_slot_unlock(ht, idx);
			return 0;
		}
		it = it->next;
	}
	ht_slot_unlock(ht, idx);
	return 0;
}
Example #8
0
int ht_iterator_start(str *iname, str *hname)
{
	int i;
	int k;

	k = -1;
	for(i=0; i<HT_ITERATOR_SIZE; i++)
	{
		if(_ht_iterators[i].name.len>0)
		{
			if(_ht_iterators[i].name.len==iname->len
					&& strncmp(_ht_iterators[i].name.s, iname->s, iname->len)==0)
			{
				k = i;
				break;
			}
		} else {
			if(k==-1) k = i;
		}
	}
	if(k==-1)
	{
		LM_ERR("no iterator available - max number is %d\n", HT_ITERATOR_SIZE);
		return -1;
	}
	if(_ht_iterators[k].name.len>0)
	{
		if(_ht_iterators[k].ht!=NULL && _ht_iterators[k].it!=NULL)
		{
			if(_ht_iterators[k].slot>=0 && _ht_iterators[k].slot<_ht_iterators[k].ht->htsize)
			{
				ht_slot_unlock(_ht_iterators[k].ht, _ht_iterators[k].slot);
			}
		}
	} else {
		if(iname->len>=HT_ITERATOR_NAME_SIZE)
		{
			LM_ERR("iterator name is too big [%.*s] (max %d)\n",
					iname->len, iname->s, HT_ITERATOR_NAME_SIZE);
			return -1;
		}
		strncpy(_ht_iterators[k].bname, iname->s, iname->len);
		_ht_iterators[k].bname[iname->len] = '\0';
		_ht_iterators[k].name.len = iname->len;
		_ht_iterators[k].name.s = _ht_iterators[k].bname;
	}
	_ht_iterators[k].it = NULL;
	_ht_iterators[k].slot = 0;
	_ht_iterators[k].ht = ht_get_table(hname);
	if(_ht_iterators[k].ht==NULL)
	{
		LM_ERR("cannot get hash table [%.*s]\n", hname->len, hname->s);
		return -1;
	}
	return 0;
}
Example #9
0
int ht_del_cell(ht_t *ht, str *name)
{
	unsigned int idx;
	unsigned int hid;
	ht_cell_t *it;

	if(ht==NULL || ht->entries==NULL)
		return -1;

	hid = ht_compute_hash(name);

	idx = ht_get_entry(hid, ht->htsize);

	/* head test and return */
	if(ht->entries[idx].first==NULL)
		return 0;

	ht_slot_lock(ht, idx);
	it = ht->entries[idx].first;
	while(it!=NULL && it->cellid < hid)
		it = it->next;
	while(it!=NULL && it->cellid == hid)
	{
		if(name->len==it->name.len
				&& strncmp(name->s, it->name.s, name->len)==0)
		{
			/* found */
			if(it->prev==NULL)
				ht->entries[idx].first = it->next;
			else
				it->prev->next = it->next;
			if(it->next)
				it->next->prev = it->prev;
			ht->entries[idx].esize--;
			ht_slot_unlock(ht, idx);
			ht_cell_free(it);
			return 0;
		}
		it = it->next;
	}
	ht_slot_unlock(ht, idx);
	return 0;
}
Example #10
0
int ht_rm_cell_re(str *sre, ht_t *ht, int mode)
{
	ht_cell_t *it;
	ht_cell_t *it0;
	int i;
	regex_t re;
	int match;
	regmatch_t pmatch;

	if(sre==NULL || sre->len<=0 || ht==NULL)
		return -1;

	if (regcomp(&re, sre->s, REG_EXTENDED|REG_ICASE|REG_NEWLINE))
	{
		LM_ERR("bad re %s\n", sre->s);
		return -1;
	}

	for(i=0; i<ht->htsize; i++)
	{
		/* free entries */
		ht_slot_lock(ht, i);
		it = ht->entries[i].first;
		while(it)
		{
			it0 = it->next;
			match = 0;
			if(mode==0)
			{
				if (regexec(&re, it->name.s, 1, &pmatch, 0)==0)
					match = 1;
			} else {
				if(it->flags&AVP_VAL_STR)
					if (regexec(&re, it->value.s.s, 1, &pmatch, 0)==0)
						match = 1;
			}
			if(match==1)
			{
				if(it->prev==NULL)
					ht->entries[i].first = it->next;
				else
					it->prev->next = it->next;
				if(it->next)
					it->next->prev = it->prev;
				ht->entries[i].esize--;
				ht_cell_free(it);
			}
			it = it0;
		}
		ht_slot_unlock(ht, i);
	}
	regfree(&re);
	return 0;
}
Example #11
0
void ht_timer(unsigned int ticks, void *param)
{
	ht_t *ht;
	ht_cell_t *it;
	ht_cell_t *it0;
	time_t now;
	int i;
	int istart;
	int istep;

	if(_ht_root==NULL)
		return;

	now = time(NULL);

	istart = (int)(long)param;
	if(ht_timer_procs<=0) istep = 1;
	else istep = ht_timer_procs;

	ht = _ht_root;
	while(ht)
	{
		if(ht->htexpire>0)
		{
			for(i=istart; i<ht->htsize; i+=istep)
			{
				/* free entries */
				ht_slot_lock(ht, i);
				it = ht->entries[i].first;
				while(it)
				{
					it0 = it->next;
					if(it->expire!=0 && it->expire<now)
					{
						/* expired */
						ht_handle_expired_record(ht, it);
						if(it->prev==NULL)
							ht->entries[i].first = it->next;
						else
							it->prev->next = it->next;
						if(it->next)
							it->next->prev = it->prev;
						ht->entries[i].esize--;
						ht_cell_free(it);
					}
					it = it0;
				}
				ht_slot_unlock(ht, i);
			}
		}
		ht = ht->next;
	}
	return;
}
Example #12
0
int ht_rm_cell_op(str *sre, ht_t *ht, int mode, int op)
{
	ht_cell_t *it;
	ht_cell_t *it0;
	int match;
	int i;

	if(sre==NULL || sre->len<=0 || ht==NULL)
		return -1;

	for(i=0; i<ht->htsize; i++)
	{
		/* free entries */
		ht_slot_lock(ht, i);
		it = ht->entries[i].first;
		while(it)
		{
			it0 = it->next;
			match = 0;
			if(mode==0)
			{
				if(op==HT_RM_OP_SW) {
					if(sre->len<=it->name.len
							&& strncmp(it->name.s, sre->s, sre->len)==0) {
						match = 1;
					}
				}
			} else {
				if(op==HT_RM_OP_SW) {
					if(it->flags&AVP_VAL_STR) {
						if(sre->len<=it->value.s.len
								&& strncmp(it->value.s.s, sre->s, sre->len)==0) {
							match = 1;
						}
					}
				}
			}
			if(match==1)
			{
				if(it->prev==NULL)
					ht->entries[i].first = it->next;
				else
					it->prev->next = it->next;
				if(it->next)
					it->next->prev = it->prev;
				ht->entries[i].esize--;
				ht_cell_free(it);
			}
			it = it0;
		}
		ht_slot_unlock(ht, i);
	}
	return 0;
}
Example #13
0
static void  htable_rpc_stats(rpc_t* rpc, void* c)
{
	ht_t *ht;
	void* th;
	unsigned int min;
	unsigned int max;
	unsigned int all;
	unsigned int i;

	ht = ht_get_root();
	if(ht==NULL)
	{
		rpc->fault(c, 500, "No htables");
		return;
	}
	while (ht != NULL)
	{
		/* add entry node */
		if (rpc->add(c, "{", &th) < 0)
		{
			rpc->fault(c, 500, "Internal error creating structure rpc");
			goto error;
		}
		all = 0;
		max = 0;
		min = 4294967295U;
		for(i=0; i<ht->htsize; i++) {
			ht_slot_lock(ht, i);
			if(ht->entries[i].esize<min)
				min = ht->entries[i].esize;
			if(ht->entries[i].esize>max)
				max = ht->entries[i].esize;
			all += ht->entries[i].esize;
			ht_slot_unlock(ht, i);
		}

		if(rpc->struct_add(th, "Sdddd",
						"name", &ht->name,	/* str */
						"slots", (int)ht->htsize,	/* uint */
						"all", (int)all,	/* uint */
						"min", (int)min,	/* uint */
						"max", (int)max		/* uint */
						) < 0) {
			rpc->fault(c, 500, "Internal error creating rpc structure");
			goto error;
		}
		ht = ht->next;
	}

error:
	return;
}
Example #14
0
int ht_get_cell_expire(ht_t *ht, str *name, unsigned int *val)
{
	unsigned int idx;
	unsigned int hid;
	ht_cell_t *it;
	time_t now;

	if(ht==NULL || ht->entries==NULL)
		return -1;

	*val = 0;
	/* not auto-expire htable */
	if(ht->htexpire==0)
		return 0;

	hid = ht_compute_hash(name);

	idx = ht_get_entry(hid, ht->htsize);

	now = time(NULL);
	ht_slot_lock(ht, idx);
	it = ht->entries[idx].first;
	while(it!=NULL && it->cellid < hid)
		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 */
			*val = (unsigned int)(it->expire - now);
			ht_slot_unlock(ht, idx);
			return 0;
		}
		it = it->next;
	}
	ht_slot_unlock(ht, idx);
	return 0;
}
Example #15
0
/**
 * unlock the slot for a given key in a hash table
 */
static int w_ht_slot_unlock(struct sip_msg* msg, char* key, char* foo)
{
	ht_pv_t *hpv;
	str skey;
	pv_spec_t *sp;
	unsigned int hid;
	unsigned int idx;

	sp = (pv_spec_t*)key;

	hpv = (ht_pv_t*)sp->pvp.pvn.u.dname;

	if(hpv->ht==NULL)
	{
		hpv->ht = ht_get_table(&hpv->htname);
		if(hpv->ht==NULL) {
			LM_ERR("cannot get $sht root\n");
			return -11;
		}
	}
	if(pv_printf_s(msg, hpv->pve, &skey)!=0)
	{
		LM_ERR("cannot get $sht key\n");
		return -1;
	}

	hid = ht_compute_hash(&skey);

	idx = ht_get_entry(hid, hpv->ht->htsize);

	LM_DBG("unlocking slot %.*s[%u] for key %.*s\n",
			hpv->htname.len, hpv->htname.s,
			idx, skey.len, skey.s);

	ht_slot_unlock(hpv->ht, idx);

	return 1;
}
Example #16
0
/*! \brief RPC htable.dump command to print content of a hash table */
static void  htable_rpc_dump(rpc_t* rpc, void* c)
{
	str htname;
	ht_t *ht;
	ht_cell_t *it;
	int i;
	void* th;
	void* ih;
	void* vh;

	if (rpc->scan(c, "S", &htname) < 1)
	{
		rpc->fault(c, 500, "No htable name given");
		return;
	}
	ht = ht_get_table(&htname);
	if(ht==NULL)
	{
		rpc->fault(c, 500, "No such htable");
		return;
	}
	for(i=0; i<ht->htsize; i++)
	{
		ht_slot_lock(ht, i);
		it = ht->entries[i].first;
		if(it)
		{
			/* add entry node */
			if (rpc->add(c, "{", &th) < 0)
			{
				rpc->fault(c, 500, "Internal error creating rpc");
				goto error;
			}
			if(rpc->struct_add(th, "dd{",
							"entry", i,
							"size",  (int)ht->entries[i].esize,
							"slot",  &ih)<0)
			{
				rpc->fault(c, 500, "Internal error creating rpc");
				goto error;
			}
			while(it)
			{
				if(rpc->struct_add(ih, "{",
							"item", &vh)<0)
				{
					rpc->fault(c, 500, "Internal error creating rpc");
					goto error;
				}
				if(it->flags&AVP_VAL_STR) {
					if(rpc->struct_add(vh, "SSs",
							"name",  &it->name.s,
							"value", &it->value.s,
							"type", "str")<0)
					{
						rpc->fault(c, 500, "Internal error adding item");
						goto error;
					}
				} else {
					if(rpc->struct_add(vh, "Sds",
							"name",  &it->name.s,
							"value", (int)it->value.n,
							"type", "int")<0)
					{
						rpc->fault(c, 500, "Internal error adding item");
						goto error;
					}
				}
				it = it->next;
			}
		}
		ht_slot_unlock(ht, i);
	}

	return;

error:
	ht_slot_unlock(ht, i);
}
Example #17
0
static struct mi_root* ht_mi_dump(struct mi_root* cmd_tree, void* param)
{
	struct mi_node* node;
	struct mi_node* node2;
	struct mi_root *rpl_tree;
	struct mi_node *rpl;
	str htname;
	ht_t *ht;
	ht_cell_t *it;
	int i;
	int len;
	char *p;

	node = cmd_tree->node.kids;
	if(node == NULL)
		return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
	htname = node->value;
	if(htname.len<=0 || htname.s==NULL)
	{
		LM_ERR("bad hash table name\n");
		return init_mi_tree( 500, "bad hash table name", 19);
	}
	ht = ht_get_table(&htname);
	if(ht==NULL)
	{
		LM_ERR("bad hash table name\n");
		return init_mi_tree( 500, "no such hash table", 18);
	}

	rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
	if (rpl_tree==NULL)
		return 0;
	rpl = &rpl_tree->node;

	for(i=0; i<ht->htsize; i++)
	{
		ht_slot_lock(ht, i);
		it = ht->entries[i].first;
		if(it)
		{
			/* add entry node */
			p = int2str((unsigned long)i, &len);
			node = add_mi_node_child(rpl, MI_DUP_VALUE, "Entry", 5, p, len);
			if (node==0)
				goto error;
			while(it)
			{
				if(it->flags&AVP_VAL_STR) {
					node2 = add_mi_node_child(node, MI_DUP_VALUE, it->name.s, it->name.len,
							it->value.s.s, it->value.s.len);
				} else {
					p = sint2str((long)it->value.n, &len);
					node2 = add_mi_node_child(node, MI_DUP_VALUE, it->name.s, it->name.len,
							p, len);
				}
				if (node2==0)
					goto error;
				it = it->next;
			}
		}
		ht_slot_unlock(ht, i);
	}

	return rpl_tree;
error:
	free_mi_tree(rpl_tree);
	return 0;
}
Example #18
0
static struct mi_root* ht_mi_reload(struct mi_root* cmd_tree, void* param)
{
	struct mi_node* node;
	str htname;
	ht_t *ht;
	ht_t nht;
	ht_cell_t *first;
	ht_cell_t *it;
	int i;

	if(ht_db_url.len<=0)
		return init_mi_tree(500, MI_ERR_RELOAD, MI_ERR_RELOAD_LEN);

	if(ht_db_init_con()!=0)
		return init_mi_tree(500, MI_ERR_RELOAD, MI_ERR_RELOAD_LEN);
	if(ht_db_open_con()!=0)
		return init_mi_tree(500, MI_ERR_RELOAD, MI_ERR_RELOAD_LEN);

	node = cmd_tree->node.kids;
	if(node == NULL)
	{
		ht_db_close_con();
		return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
	}
	htname = node->value;
	if(htname.len<=0 || htname.s==NULL)
	{
		LM_ERR("bad hash table name\n");
		ht_db_close_con();
		return init_mi_tree( 500, "bad hash table name", 19);
	}
	ht = ht_get_table(&htname);
	if(ht==NULL || ht->dbtable.len<=0)
	{
		LM_ERR("bad hash table name\n");
		ht_db_close_con();
		return init_mi_tree( 500, "no such hash table", 18);
	}
	memcpy(&nht, ht, sizeof(ht_t));
	/* it's temporary operation - use system malloc */
	nht.entries = (ht_entry_t*)malloc(nht.htsize*sizeof(ht_entry_t));
	if(nht.entries == NULL)
	{
		ht_db_close_con();
		return init_mi_tree(500, MI_ERR_RELOAD, MI_ERR_RELOAD_LEN);
	}
	memset(nht.entries, 0, nht.htsize*sizeof(ht_entry_t));

	if(ht_db_load_table(&nht, &ht->dbtable, 0)<0)
	{
		/* free any entry set if it was a partial load */
		for(i=0; i<nht.htsize; i++)
		{
			first = nht.entries[i].first;
			while(first)
			{
				it = first;
				first = first->next;
				ht_cell_free(it);
			}
		}
		free(nht.entries);
		ht_db_close_con();
		return init_mi_tree(500, MI_ERR_RELOAD, MI_ERR_RELOAD_LEN);
	}

	/* replace old entries */
	for(i=0; i<nht.htsize; i++)
	{
		ht_slot_lock(ht, i);
		first = ht->entries[i].first;
		ht->entries[i].first = nht.entries[i].first;
		ht->entries[i].esize = nht.entries[i].esize;
		ht_slot_unlock(ht, i);
		nht.entries[i].first = first;
	}
	/* free old entries */
	for(i=0; i<nht.htsize; i++)
	{
		first = nht.entries[i].first;
		while(first)
		{
			it = first;
			first = first->next;
			ht_cell_free(it);
		}
	}
	free(nht.entries);
	ht_db_close_con();
	return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
}
Example #19
0
/*! \brief RPC htable.reload command to reload content of a hash table */
static void htable_rpc_reload(rpc_t* rpc, void* c)
{
	str htname;
	ht_t *ht;
	ht_t nht;
	ht_cell_t *first;
	ht_cell_t *it;
	int i;

	if(ht_db_url.len<=0) {
		rpc->fault(c, 500, "No htable db_url");
		return;
	}
	if(ht_db_init_con()!=0) {
		rpc->fault(c, 500, "Failed to init htable db connection");
		return;
	}
	if(ht_db_open_con()!=0) {
		rpc->fault(c, 500, "Failed to open htable db connection");
		return;
	}

	if (rpc->scan(c, "S", &htname) < 1)
	{
		rpc->fault(c, 500, "No htable name given");
		return;
	}
	ht = ht_get_table(&htname);
	if(ht==NULL)
	{
		rpc->fault(c, 500, "No such htable");
		return;
	}


	memcpy(&nht, ht, sizeof(ht_t));
	/* it's temporary operation - use system malloc */
	nht.entries = (ht_entry_t*)malloc(nht.htsize*sizeof(ht_entry_t));
	if(nht.entries == NULL)
	{
		ht_db_close_con();
		rpc->fault(c, 500, "Mtree reload failed");
		return;
	}
	memset(nht.entries, 0, nht.htsize*sizeof(ht_entry_t));

	if(ht_db_load_table(&nht, &ht->dbtable, 0)<0)
	{
		/* free any entry set if it was a partial load */
		for(i=0; i<nht.htsize; i++)
		{
			first = nht.entries[i].first;
			while(first)
			{
				it = first;
				first = first->next;
				ht_cell_free(it);
			}
		}
		free(nht.entries);
		ht_db_close_con();
		rpc->fault(c, 500, "Mtree reload failed");
		return;
	}

	/* replace old entries */
	for(i=0; i<nht.htsize; i++)
	{
		ht_slot_lock(ht, i);
		first = ht->entries[i].first;
		ht->entries[i].first = nht.entries[i].first;
		ht->entries[i].esize = nht.entries[i].esize;
		ht_slot_unlock(ht, i);
		nht.entries[i].first = first;
	}
	/* free old entries */
	for(i=0; i<nht.htsize; i++)
	{
		first = nht.entries[i].first;
		while(first)
		{
			it = first;
			first = first->next;
			ht_cell_free(it);
		}
	}
	free(nht.entries);
	ht_db_close_con();
	return;
}
Example #20
0
int ht_count_cells_re(str *sre, ht_t *ht, int mode)
{
	ht_cell_t *it;
	ht_cell_t *it0;
	int i;
	regex_t re;
	regmatch_t pmatch;
	int cnt = 0;
	int op = 0;
	str sval;
	str tval;
	int ival = 0;

	if(sre==NULL || sre->len<=0 || ht==NULL)
		return 0;

	if(sre->len>=2)
	{
		switch(sre->s[0]) {
			case '~':
				switch(sre->s[1]) {
					case '~':
						op = 1; /* regexp */
					break;
					case '%':
						op = 2; /* rlike */
					break;
				}
			break;
			case '%':
				switch(sre->s[1]) {
					case '~':
						op = 3; /* llike */
					break;
				}
			break;
			case '=':
				switch(sre->s[1]) {
					case '=':
						op = 4; /* str eq */
					break;
				}
			break;
			case 'e':
				switch(sre->s[1]) {
					case 'q':
						op = 5; /* int eq */
					break;
				}
			break;
			case '*':
				switch(sre->s[1]) {
					case '*':
						op = 6; /* int eq */
					break;
				}
			break;
		}
	}

	if(op==6) {
		/* count all */
		for(i=0; i<ht->htsize; i++)
			cnt += ht->entries[i].esize;
		return cnt;
	}

	if(op > 0) {
		if(sre->len<=2)
			return 0;
		sval = *sre;
		sval.s += 2;
		sval.len -= 2;
		if(op==5) {
			if(mode==0)
			{
				/* match by name */
				return 0;
			}
			str2sint(&sval, &ival);
		}
	} else {
		sval = *sre;
		op = 1;
	}

	if(op==1)
	{
		if (regcomp(&re, sval.s, REG_EXTENDED|REG_ICASE|REG_NEWLINE))
		{
			LM_ERR("bad re %s\n", sre->s);
			return 0;
		}
	}

	for(i=0; i<ht->htsize; i++)
	{
		/* free entries */
		ht_slot_lock(ht, i);
		it = ht->entries[i].first;
		while(it)
		{
			it0 = it->next;
			if(op==5)
			{
				if(!(it->flags&AVP_VAL_STR))
					if( it->value.n==ival)
						cnt++;
			} else {
				tval.len = -1;
				if(mode==0)
				{
					/* match by name */
					tval = it->name;
				} else {
					if(it->flags&AVP_VAL_STR)
						tval = it->value.s;
				}
				if(tval.len>-1) {
					switch(op) {
						case 1: /* regexp */
							if (regexec(&re, tval.s, 1, &pmatch, 0)==0)
								cnt++;
						break;
						case 2: /* rlike */
							if(sval.len<=tval.len
									&& strncmp(sval.s,
										tval.s+tval.len-sval.len, sval.len)==0)
								cnt++;
						break;
						case 3: /* llike */
							if(sval.len<=tval.len
									&& strncmp(sval.s, tval.s, sval.len)==0)
								cnt++;
						break;
						case 4: /* str eq */
							if(sval.len==tval.len
									&& strncmp(sval.s, tval.s, sval.len)==0)
								cnt++;
						break;
					}
				}
			}
			it = it0;
		}
		ht_slot_unlock(ht, i);
	}
	if(op==1)
		regfree(&re);
	return cnt;
}
Example #21
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) ht_slot_lock(ht, idx);
	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)
		{
			/* found */
			if(now>0 && it->expire!=0 && it->expire<now) {
				/* entry has expired */
				ht_handle_expired_record(ht, it);

				if(ht->flags==PV_VAL_INT) {
					/* initval is integer, use it to create a fresh entry */
					it->flags &= ~AVP_VAL_STR;
					it->value.n = ht->initval.n;
					/* increment will be done below */
				} else {
					/* delete expired entry */
					if(it->prev==NULL)
						ht->entries[idx].first = it->next;
					else
						it->prev->next = it->next;
					if(it->next)
						it->next->prev = it->prev;
					ht->entries[idx].esize--;
					if(mode) ht_slot_unlock(ht, idx);
					ht_cell_free(it);
					return NULL;
				}
			}
			/* update value */
			if(it->flags&AVP_VAL_STR)
			{
				/* string value cannot be incremented */
				if(mode) ht_slot_unlock(ht, idx);
				return NULL;
			} else {
				it->value.n += val;
				if(ht->updateexpire)
					it->expire = now + ht->htexpire;
				if(old!=NULL)
				{
					if(old->msize>=it->msize)
					{
						memcpy(old, it, it->msize);
						if(mode) ht_slot_unlock(ht, idx);
						return old;
					}
				}
				cell = (ht_cell_t*)pkg_malloc(it->msize);
				if(cell!=NULL)
					memcpy(cell, it, it->msize);

				if(mode) ht_slot_unlock(ht, idx);
				return cell;
			}
		}
		prev = it;
		it = it->next;
	}
	/* add val if htable has an integer init value */
	if(ht->flags!=PV_VAL_INT)
	{
		if(mode) ht_slot_unlock(ht, idx);
		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) ht_slot_unlock(ht, idx);
		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);
			if(mode) ht_slot_unlock(ht, idx);
			return old;
		}
	}
	cell = (ht_cell_t*)pkg_malloc(it->msize);
	if(cell!=NULL)
		memcpy(cell, it, it->msize);

	if(mode) ht_slot_unlock(ht, idx);
	return cell;
}
Example #22
0
int ht_has_cell_op_str(str *sre, ht_t *ht, int mode, int op)
{
	ht_cell_t *it;
	str sm;
	int i;
	int nomatch;
	regex_t re;
	regmatch_t pmatch;

	if(sre==NULL || sre->len<=0 || ht==NULL)
		return -1;

	if(op == HT_RM_OP_RE) {
		if (regcomp(&re, sre->s, REG_EXTENDED|REG_ICASE|REG_NEWLINE)) {
			LM_ERR("bad re %s\n", sre->s);
			return -1;
		}
	}

	for(i=0; i<ht->htsize; i++) {
		/* free entries */
		ht_slot_lock(ht, i);
		it = ht->entries[i].first;
		while(it) {
			nomatch = 0;
			if(mode==0) {
				sm = it->name;
			} else {
				if(it->flags&AVP_VAL_STR) {
					sm = it->value.s;
				} else {
					/* no str value - skip matching */
					nomatch = 1;
				}
			}
			if(nomatch==0) {
				switch(op) {
					case HT_RM_OP_EQ:
						if(sre->len==sm.len
									&& strncmp(sm.s, sre->s, sre->len)==0) {
							goto matched;
						}
					break;
					case HT_RM_OP_NE:
						if(sre->len!=sm.len
									|| strncmp(sm.s, sre->s, sre->len)!=0) {
							goto matched;
						}
					break;
					case HT_RM_OP_SW:
						if(sre->len<=sm.len
									&& strncmp(sm.s, sre->s, sre->len)==0) {
							goto matched;
						}
					break;
					case HT_RM_OP_RE:
						if (regexec(&re, sm.s, 1, &pmatch, 0)==0) {
							goto matched;
						}
					break;
					default:
						ht_slot_unlock(ht, i);
						LM_ERR("unsupported matching operator: %d\n", op);
						return -1;
				}
			}
			it = it->next;
		}
		ht_slot_unlock(ht, i);
	}
	if(op==HT_RM_OP_RE) {
		regfree(&re);
	}
	return -1;

matched:
	ht_slot_unlock(ht, i);
	if(op==HT_RM_OP_RE) {
		regfree(&re);
	}
	return 1;
}
Example #23
0
int ht_set_cell(ht_t *ht, str *name, int type, int_str *val, int mode)
{
	unsigned int idx;
	unsigned int hid;
	ht_cell_t *it, *prev, *cell;
	time_t now;

	if(ht==NULL || ht->entries==NULL)
		return -1;

	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) ht_slot_lock(ht, idx);
	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)
			{
				if(type&AVP_VAL_STR)
				{
					if(it->value.s.len >= val->s.len)
					{
						/* copy */
						it->value.s.len = val->s.len;
						memcpy(it->value.s.s, val->s.s, val->s.len);
						it->value.s.s[it->value.s.len] = '\0';

						if(ht->updateexpire)
							it->expire = now + ht->htexpire;
					} else {
						/* new */
						cell = ht_cell_new(name, type, val, hid);
						if(cell == NULL)
						{
							LM_ERR("cannot create new cell\n");
							if(mode) ht_slot_unlock(ht, idx);
							return -1;
						}
						cell->next = it->next;
						cell->prev = it->prev;
						if(ht->updateexpire)
							cell->expire = now + ht->htexpire;
						else
							cell->expire = it->expire;
						if(it->prev)
							it->prev->next = cell;
						else
							ht->entries[idx].first = cell;
						if(it->next)
							it->next->prev = cell;
						ht_cell_free(it);
					}
				} else {
					it->flags &= ~AVP_VAL_STR;
					it->value.n = val->n;

					if(ht->updateexpire)
						it->expire = now + ht->htexpire;
				}
				if(mode) ht_slot_unlock(ht, idx);
				return 0;
			} else {
				if(type&AVP_VAL_STR)
				{
					/* new */
					cell = ht_cell_new(name, type, val, hid);
					if(cell == NULL)
					{
						LM_ERR("cannot create new cell.\n");
						if(mode) ht_slot_unlock(ht, idx);
						return -1;
					}
					if(ht->updateexpire)
						cell->expire = now + ht->htexpire;
					else
						cell->expire = it->expire;
					cell->next = it->next;
					cell->prev = it->prev;
					if(it->prev)
						it->prev->next = cell;
					else
						ht->entries[idx].first = cell;
					if(it->next)
						it->next->prev = cell;
					ht_cell_free(it);
				} else {
					it->value.n = val->n;

					if(ht->updateexpire)
						it->expire = now + ht->htexpire;
				}
				if(mode) ht_slot_unlock(ht, idx);
				return 0;
			}
		}
		prev = it;
		it = it->next;
	}
	/* add */
	cell = ht_cell_new(name, type, val, hid);
	if(cell == NULL)
	{
		LM_ERR("cannot create new cell.\n");
		if(mode) ht_slot_unlock(ht, idx);
		return -1;
	}
	cell->expire = now + ht->htexpire;
	if(prev==NULL)
	{
		if(ht->entries[idx].first!=NULL)
		{
			cell->next = ht->entries[idx].first;
			ht->entries[idx].first->prev = cell;
		}
		ht->entries[idx].first = cell;
	} else {
		cell->next = prev->next;
		cell->prev = prev;
		if(prev->next)
			prev->next->prev = cell;
		prev->next = cell;
	}
	ht->entries[idx].esize++;
	if(mode) ht_slot_unlock(ht, idx);
	return 0;
}