/*! * \brief Get the size of a profile * \param profile evaluated profile * \param value value * \return the profile size */ unsigned int get_profile_size(struct dlg_profile_table *profile, str *value) { unsigned int n,i; struct dlg_profile_hash *ph; if (profile->has_value==0 || value==NULL) { /* iterate through the hash and count all records */ lock_get( &profile->lock ); for( i=0,n=0 ; i<profile->size ; i++ ) n += profile->entries[i].content; lock_release( &profile->lock ); return n; } else { /* iterate through the hash entry and count only matching */ /* calculate the hash position */ i = calc_hash_profile( value, NULL, profile); n = 0; lock_get( &profile->lock ); ph = profile->entries[i].first; if(ph) { do { /* compare */ if ( value->len==ph->value.len && memcmp(value->s,ph->value.s,value->len)==0 ) { /* found */ n++; } /* next */ ph=ph->next; }while( ph!=profile->entries[i].first ); } lock_release( &profile->lock ); return n; } }
/*! * \brief Link a dialog profile * \param linker dialog linker * \param dlg dialog cell */ static void link_dlg_profile(struct dlg_profile_link *linker, struct dlg_cell *dlg) { unsigned int hash; struct dlg_profile_entry *p_entry; struct dlg_entry *d_entry; /* add the linker to the dialog */ /* FIXME zero h_id is not 100% for testing if the dialog is inserted * into the hash table -> we need circular lists -bogdan */ if (dlg->h_id) { d_entry = &d_table->entries[dlg->h_entry]; dlg_lock( d_table, d_entry); linker->next = dlg->profile_links; dlg->profile_links =linker; linker->hash_linker.dlg = dlg; dlg_unlock( d_table, d_entry); } else { linker->next = dlg->profile_links; dlg->profile_links =linker; linker->hash_linker.dlg = dlg; } /* calculate the hash position */ hash = calc_hash_profile(&linker->hash_linker.value, dlg, linker->profile); linker->hash_linker.hash = hash; /* insert into profile hash table */ p_entry = &linker->profile->entries[hash]; lock_get( &linker->profile->lock ); if (p_entry->first) { linker->hash_linker.prev = p_entry->first->prev; linker->hash_linker.next = p_entry->first; p_entry->first->prev->next = &linker->hash_linker; p_entry->first->prev = &linker->hash_linker; } else { p_entry->first = linker->hash_linker.next = linker->hash_linker.prev = &linker->hash_linker; } p_entry->content ++; lock_release( &linker->profile->lock ); }
/*! * \brief Remove profile * \param profile pointer to profile * \param value profile value * \param puid profile unique id */ int remove_profile(dlg_profile_table_t *profile, str *value, str *puid) { unsigned int hash; struct dlg_profile_entry *p_entry; struct dlg_profile_hash *lh; hash = calc_hash_profile(value, puid, profile); lock_get(&profile->lock ); p_entry = &profile->entries[hash]; lh = p_entry->first; if(lh) { do { if(lh->dlg==NULL && lh->puid_len==puid->len && lh->value.len==value->len && strncmp(lh->puid, puid->s, puid->len)==0 && strncmp(lh->value.s, value->s, value->len)==0) { /* last element on the list? */ if (lh==lh->next) { p_entry->first = NULL; } else { if (p_entry->first==lh) p_entry->first = lh->next; lh->next->prev = lh->prev; lh->prev->next = lh->next; } lh->next = lh->prev = NULL; if(lh->linker) shm_free(lh->linker); p_entry->content--; lock_release(&profile->lock ); return 1; } lh = lh->next; } while(lh != p_entry->first); } lock_release(&profile->lock ); return 0; }
/*! * \brief Link a dialog profile * \param linker dialog linker * \param vkey key for profile hash table */ static void link_profile(struct dlg_profile_link *linker, str *vkey) { unsigned int hash; struct dlg_profile_entry *p_entry; /* calculate the hash position */ hash = calc_hash_profile(&linker->hash_linker.value, vkey, linker->profile); linker->hash_linker.hash = hash; /* insert into profile hash table */ p_entry = &linker->profile->entries[hash]; lock_get( &linker->profile->lock ); if (p_entry->first) { linker->hash_linker.prev = p_entry->first->prev; linker->hash_linker.next = p_entry->first; p_entry->first->prev->next = &linker->hash_linker; p_entry->first->prev = &linker->hash_linker; } else { p_entry->first = linker->hash_linker.next = linker->hash_linker.prev = &linker->hash_linker; } p_entry->content ++; lock_release( &linker->profile->lock ); }
int dlg_set_timeout_by_profile(struct dlg_profile_table *profile, str *value, int timeout) { unsigned int i = 0; dlg_cell_t *this_dlg = NULL; struct dlg_profile_hash *ph = NULL; /* Private structure necessary for manipulating dialog * timeouts outside of profile locks. Admittedly, an * ugly hack, but avoids some concurrency issues. */ struct dlg_map_list { unsigned int h_id; unsigned int h_entry; struct dlg_map_list *next; } *map_head, *map_scan, *map_scan_next; map_head = NULL; /* If the profile has no value, iterate through every * node and set its timeout. */ if(profile->has_value == 0 || value == NULL) { lock_get(&profile->lock); for(i = 0; i < profile->size; i ++) { ph = profile->entries[i].first; if(!ph) continue; do { struct dlg_map_list *d = malloc(sizeof(struct dlg_map_list)); if(!d) return -1; memset(d, 0, sizeof(struct dlg_map_list)); d->h_id = ph->dlg->h_id; d->h_entry = ph->dlg->h_entry; if(map_head == NULL) map_head = d; else { d->next = map_head; map_head = d; } ph = ph->next; } while(ph != profile->entries[i].first); } lock_release(&profile->lock); } else { i = calc_hash_profile(value, NULL, profile); lock_get(&profile->lock); ph = profile->entries[i].first; if(ph) { do { if(ph && value->len == ph->value.len && memcmp(value->s, ph->value.s, value->len) == 0) { struct dlg_map_list *d = malloc(sizeof(struct dlg_map_list)); if(!d) return -1; memset(d, 0, sizeof(struct dlg_map_list)); d->h_id = ph->dlg->h_id; d->h_entry = ph->dlg->h_entry; if(map_head == NULL) map_head = d; else { d->next = map_head; map_head = d; } } ph = ph->next; } while(ph && ph != profile->entries[i].first); } lock_release(&profile->lock); } /* Walk the list and bulk-set the timeout */ for(map_scan = map_head; map_scan != NULL; map_scan = map_scan_next) { map_scan_next = map_scan->next; this_dlg = dlg_lookup(map_scan->h_entry, map_scan->h_id); if(!this_dlg) { LM_CRIT("Unable to find dialog %d:%d\n", map_scan->h_entry, map_scan->h_id); } else if(this_dlg->state >= DLG_STATE_EARLY) { if(update_dlg_timeout(this_dlg, timeout) < 0) { LM_ERR("Unable to set timeout on %d:%d\n", map_scan->h_entry, map_scan->h_id); } dlg_release(this_dlg); } free(map_scan); } return 0; }