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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
/** * 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; }
/*! \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); }
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; }
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); }
/*! \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; }
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; }
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; }
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; }
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; }