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; }
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; }
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, delete it and return NULL */ ht_handle_expired_record(ht, it); 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 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; }
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; }