Example #1
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;
	
	lock_get(&ht->entries[idx].lock);
	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, delete it and return NULL */
				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--;
				lock_release(&ht->entries[idx].lock);
				ht_cell_free(it);
				return NULL;
			}
			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);
			lock_release(&ht->entries[idx].lock);
			return cell;
		}
		it = it->next;
	}
	lock_release(&ht->entries[idx].lock);
	return NULL;
}
Example #2
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 #3
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 */
		lock_get(&ht->entries[i].lock);
		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;
		}
		lock_release(&ht->entries[i].lock);
	}
	regfree(&re);
	return 0;
}
Example #4
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 #5
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 #6
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;

	if(_ht_root==NULL)
		return;

	now = time(NULL);
	
	ht = _ht_root;
	while(ht)
	{
		if(ht->htexpire>0)
		{
			for(i=0; i<ht->htsize; i++)
			{
				/* free entries */
				lock_get(&ht->entries[i].lock);
				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;
				}
				lock_release(&ht->entries[i].lock);
			}
		}
		ht = ht->next;
	}
	return;
}
Example #7
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;
	
	lock_get(&ht->entries[idx].lock);
	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--;
			lock_release(&ht->entries[idx].lock);
			ht_cell_free(it);
			return 0;
		}
		it = it->next;
	}
	lock_release(&ht->entries[idx].lock);
	return 0;
}
Example #8
0
int ht_destroy(void)
{
	int i;
	ht_cell_t *it, *it0;
	ht_t *ht;
	ht_t *ht0;

	if(_ht_root==NULL)
		return -1;

	ht = _ht_root;
	while(ht)
	{
		ht0 = ht->next;
		if(ht->entries!=NULL)
		{
			for(i=0; i<ht->htsize; i++)
			{
				/* free entries */
				it = ht->entries[i].first;
				while(it)
				{
					it0 = it;
					it = it->next;
					ht_cell_free(it0);
				}
				/* free locks */
				lock_destroy(&ht->entries[i].lock);
			}
			shm_free(ht->entries);
		}
		shm_free(ht);
		ht = ht0;
	}
	_ht_root = NULL;
	return 0;
}
Example #9
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 #10
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 #11
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)
		{
			/* found */
			if(now>0 && it->expire!=0 && it->expire<now) {
				/* entry has expired */
				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--;
					lock_release(&ht->entries[idx].lock);
					ht_cell_free(it);
					return NULL;
				}
			}
			/* 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;
}
Example #12
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) 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)
			{
				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) lock_release(&ht->entries[idx].lock);
							return -1;
						}
						cell->next = it->next;
						cell->prev = it->prev;
						cell->expire = now + ht->htexpire;
						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) lock_release(&ht->entries[idx].lock);
				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) lock_release(&ht->entries[idx].lock);
						return -1;
					}
					cell->expire = now + ht->htexpire;
					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) lock_release(&ht->entries[idx].lock);
				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) lock_release(&ht->entries[idx].lock);
		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) lock_release(&ht->entries[idx].lock);
	return 0;
}