Пример #1
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;
}
Пример #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;
	
	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;
}
Пример #3
0
int ht_add_table(str *name, int autoexp, str *dbtable, int size, int dbmode,
		int itype, int_str *ival, int updateexpire, int dmqreplicate)
{
	unsigned int htid;
	ht_t *ht;

	htid = ht_compute_hash(name);

	/* does it exist */
	ht = _ht_root;
	while(ht!=NULL)
	{
		if(htid == ht->htid && name->len==ht->name.len 
				&& strncmp(name->s, ht->name.s, name->len)==0)
		{
			LM_ERR("htable already configured [%.*s]\n", name->len, name->s);
			return -1;
		}
		ht = ht->next;
	}

	ht = (ht_t*)shm_malloc(sizeof(ht_t));
	if(ht==NULL)
	{
		LM_ERR("no more shared memory\n");
		return -1;
	}
	memset(ht, 0, sizeof(ht_t));

	if(size<=1)
		ht->htsize = 8;
	else if(size>31)
		ht->htsize = 1<<14;
	else ht->htsize = 1<<size;
	ht->htid = htid;
	ht->htexpire = autoexp;
	ht->updateexpire = updateexpire;
	ht->name = *name;
	if(dbtable!=NULL && dbtable->len>0)
		ht->dbtable = *dbtable;
	ht->dbmode = dbmode;
	ht->flags = itype;
	if(ival!=NULL)
		ht->initval = *ival;
	ht->dmqreplicate = dmqreplicate;
	ht->next = _ht_root;
	_ht_root = ht;
	return 0;
}
Пример #4
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);

	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)
		{
			/* update value */
			it->expire = now;
			lock_release(&ht->entries[idx].lock);
			return 0;
		}
		it = it->next;
	}
	lock_release(&ht->entries[idx].lock);
	return 0;
}
Пример #5
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;
}
Пример #6
0
ht_t* ht_get_table(str *name)
{
	unsigned int htid;
	ht_t *ht;

	htid = ht_compute_hash(name);

	/* does it exist */
	ht = _ht_root;
	while(ht!=NULL)
	{
		if(htid == ht->htid && name->len==ht->name.len 
				&& strncmp(name->s, ht->name.s, name->len)==0)
		{
			LM_DBG("htable found [%.*s]\n", name->len, name->s);
			return ht;
		}
		ht = ht->next;
	}
	return NULL;
}
Пример #7
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);
	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)
		{
			/* update value */
			*val = (unsigned int)(it->expire - now);
			lock_release(&ht->entries[idx].lock);
			return 0;
		}
		it = it->next;
	}
	lock_release(&ht->entries[idx].lock);
	return 0;
}
Пример #8
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;
}
Пример #9
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;
}
Пример #10
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;
}
Пример #11
0
int ht_add_table(str *name, int autoexp, str *dbtable, str *dbcols, int size,
		int dbmode, int itype, int_str *ival, int updateexpire,
		int dmqreplicate)
{
	unsigned int htid;
	ht_t *ht;
	int c;
	int i;

	htid = ht_compute_hash(name);

	/* does it exist */
	ht = _ht_root;
	while(ht!=NULL)
	{
		if(htid == ht->htid && name->len==ht->name.len
				&& strncmp(name->s, ht->name.s, name->len)==0)
		{
			LM_ERR("htable already configured [%.*s]\n", name->len, name->s);
			return -1;
		}
		ht = ht->next;
	}

	ht = (ht_t*)shm_malloc(sizeof(ht_t));
	if(ht==NULL)
	{
		LM_ERR("no more shared memory\n");
		return -1;
	}
	memset(ht, 0, sizeof(ht_t));

	if(size<=1)
		ht->htsize = 8;
	else if(size>31)
		ht->htsize = 1<<14;
	else ht->htsize = 1<<size;
	ht->htid = htid;
	ht->htexpire = autoexp;
	ht->updateexpire = updateexpire;
	ht->name = *name;
	if(dbtable!=NULL && dbtable->len>0)
		ht->dbtable = *dbtable;
	ht->dbmode = dbmode;
	ht->flags = itype;
	if(ival!=NULL)
		ht->initval = *ival;
	ht->dmqreplicate = dmqreplicate;

	if(dbcols!=NULL && dbcols->s!=NULL && dbcols->len>0) {
		ht->scols[0].s = (char*)shm_malloc((1+dbcols->len)*sizeof(char));
		if(ht->scols[0].s==NULL) {
			LM_ERR("no more shm memory\n");
			shm_free(ht);
			return -1;
		}
		memset(ht->scols[0].s, 0, (1+dbcols->len)*sizeof(char));
		memcpy(ht->scols[0].s, dbcols->s, dbcols->len);
		ht->scols[0].len = dbcols->len;
		c = 0;
		for(i=0; i<dbcols->len; i++) {
			if(ht->scols[0].s[i]==',') {
				ht->scols[c].len = (ht->scols[0].s + i - ht->scols[c].s);
				LM_DBG("db table column[%d]='%.*s'\n", c,
						ht->scols[c].len, ht->scols[c].s);
				c++;
				if(c>=HT_MAX_COLS) {
					LM_ERR("too many columns %d\n", c);
					shm_free(ht->scols[0].s);
					shm_free(ht);
					return -1;
				}
				ht->scols[c].s = ht->scols[0].s + i + 1;
				ht->scols[c].len = ht->scols[0].s + dbcols->len - ht->scols[c].s;
			}
		}
		LM_DBG("db table column[%d]='%.*s'\n", c,
				ht->scols[c].len, ht->scols[c].s);
		if(c==0) {
			LM_ERR("there must be at least two columns (prefix, value)\n");
			shm_free(ht->scols[0].s);
			shm_free(ht);
			return -1;
		}
		ht->ncols = c + 1;
		ht->pack[0] = 'l';
		ht->pack[1] = ',';
		ht->pack[2] = '*';
	}

	ht->next = _ht_root;
	_ht_root = ht;
	return 0;
}