void add_subscription(ims_subscription* s) { int sl; sl = core_hash(&s->private_identity, 0, subs_hash_size); lock_subscription_slot(sl); add_subscription_unsafe(s); unlock_subscription_slot(sl); }
/** * @brief Get a subscription from the subscription list based on the IMPI * NB - does not return with a lock on the subscription but does increment ref count * @param impu string of impu to search for * @param s ims_subscription to be returned if found * @param leave_slot_locked if no subscription is found return with the slot locked (in case we want to add) * @return 0 on success */ int get_subscription(str* impi_s, ims_subscription** s, int leave_slot_locked) { int subscription_hash, sl; ims_subscription* ptr; subscription_hash = core_hash(impi_s, 0, 0); sl = subscription_hash & (subs_hash_size - 1); lock_subscription_slot(sl); ptr = ims_subscription_list->slot[sl].first; while (ptr) { if ((impi_s->len == ptr->private_identity.len) && (memcmp(impi_s->s, ptr->private_identity.s, impi_s->len) == 0)) { LM_DBG("found an existing subscription for IMPI [%.*s]\n", impi_s->len, impi_s->s); (*s) = ptr; lock_subscription(ptr); ref_subscription_unsafe(ptr); unlock_subscription(ptr); unlock_subscription_slot(sl); return 0; } ptr = ptr->next; } if (!leave_slot_locked) unlock_subscription_slot(sl); return 1; }
/*! * \brief Run timer handler for given domain * \param _d domain */ void mem_timer_udomain(udomain_t* _d) { struct impurecord* ptr, *t; struct ucontact* contact_ptr; int i, n, temp; //go through contacts first n = contact_list->max_collisions; LM_DBG("*** mem_timer_udomain - checking contacts - START ***\n"); for (i = 0; i < contact_list->size; i++) { lock_contact_slot_i(i); contact_ptr = contact_list->slot[i].first; while (contact_ptr) { LM_DBG("We have a contact in the new contact list in slot %d = [%.*s] (%.*s) which expires in %lf seconds and has a ref count of %d\n", i, contact_ptr->aor.len, contact_ptr->aor.s, contact_ptr->c.len, contact_ptr->c.s, (double) contact_ptr->expires - time(NULL), contact_ptr->ref_count); //contacts are now deleted during impurecord processing contact_ptr = contact_ptr->next; } if (contact_list->slot[i].n > n) { n = contact_list->slot[i].n; } unlock_contact_slot_i(i); contact_list->max_collisions = n; } LM_DBG("*** mem_timer_udomain - checking contacts - FINISHED ***\n"); temp = 0; n = _d->max_collisions; LM_DBG("*** mem_timer_udomain - checking IMPUs - START ***\n"); for (i = 0; i < _d->size; i++) { lock_ulslot(_d, i); ptr = _d->table[i].first; temp = 0; while (ptr) { temp = 1; #ifdef EXTRA_DEBUG LM_DBG("ULSLOT %d LOCKED\n", i); #endif t = ptr; ptr = ptr->next; timer_impurecord(t); } if (temp) { #ifdef EXTRA_DEBUG LM_DBG("ULSLOT %d UN-LOCKED\n", i); #endif } if (_d->table[i].n > n) n = _d->table[i].n; unlock_ulslot(_d, i); _d->max_collisions = n; } LM_DBG("*** mem_timer_udomain - checking IMPUs - FINISHED ***\n"); n = ims_subscription_list->max_collisions; for (i = 0; i < ims_subscription_list->size; i++) { lock_subscription_slot(i); if (ims_subscription_list->slot[i].n > n) { n = ims_subscription_list->slot[i].n; } unlock_subscription_slot(i); } ims_subscription_list->max_collisions = n; }
/*! * \brief Run timer handler for given domain * \param _d domain */ void mem_timer_udomain(udomain_t* _d, int istart, int istep) { struct impurecord* ptr, *t; struct ucontact* contact_ptr; unsigned int num_expired_contacts = 0; int i, n, temp; time_t now; int abort = 0; int slot; int ref_count_db; now = time(0); if (istart == 0) { int numcontacts = contact_list->size*2; //assume we should be ok for each slot to have 2 collisions if (expired_contacts_size < numcontacts) { LM_DBG("Changing expired_contacts list size from %d to %d\n", expired_contacts_size, numcontacts); if (expired_contacts){ pkg_free(expired_contacts); } expired_contacts = (ucontact_t**)pkg_malloc(numcontacts*sizeof(ucontact_t**)); if (!expired_contacts) { LM_ERR("no more pkg mem trying to allocate [%lu] bytes\n", numcontacts*sizeof(ucontact_t**)); return; } expired_contacts_size = numcontacts; } //go through contacts first n = contact_list->max_collisions; LM_DBG("*** mem_timer_udomain - checking contacts - START ***\n"); for (i=0; i < contact_list->size; i++) { lock_contact_slot_i(i); contact_ptr = contact_list->slot[i].first; while (contact_ptr) { if (num_expired_contacts >= numcontacts) { LM_WARN("we don't have enough space to expire all contacts in this pass - will continue in next pass\n"); abort = 1; break; } LM_DBG("We have a [3gpp=%d] contact in the new contact list in slot %d = [%.*s] (%.*s) which expires in %lf seconds and has a ref count of %d (state: %s)\n", contact_ptr->is_3gpp, i, contact_ptr->aor.len, contact_ptr->aor.s, contact_ptr->c.len, contact_ptr->c.s, (double) contact_ptr->expires - now, contact_ptr->ref_count, get_contact_state_as_string(contact_ptr->state)); //contacts are now deleted during impurecord processing if ((contact_ptr->expires-now) <= 0) { if (contact_ptr->state == CONTACT_DELAYED_DELETE) { if (contact_ptr->ref_count <= 0) { LM_DBG("contact in state CONTACT_DELATED_DELETE is about to be deleted"); expired_contacts[num_expired_contacts] = contact_ptr; num_expired_contacts++; } else { /* we could fall here not because contact is still referenced but also because we failed before to get a lock to unref the contact, so we check if contact is really referenced*/ if (db_mode != NO_DB) { LM_DBG("contact in state CONTACT_DELAYED_DELETE still has a ref count of [%d] in memory. Check on DB \n", contact_ptr->ref_count); ref_count_db = db_check_if_contact_is_linked(contact_ptr); if (ref_count_db < 0) { LM_ERR("Unable to check if contact is unlinked\n"); } else if (ref_count_db == 0) { LM_DBG("Contact has ref count [%d] but there's no link on the DB. Deleting contact", contact_ptr->ref_count); contact_ptr->ref_count = 0; expired_contacts[num_expired_contacts] = contact_ptr; num_expired_contacts++; } else { LM_DBG("Contact in state CONTACT_DELAYED_DELETE has ref count [%d] on DB", ref_count_db); } } else { LM_DBG("contact in state CONTACT_DELAYED_DELETE still has a ref count of [%d] in memory. Not doing anything for now \n", contact_ptr->ref_count); } } } else if (contact_ptr->state != CONTACT_DELETED) { LM_DBG("expiring contact [%.*s].... setting to CONTACT_EXPIRE_PENDING_NOTIFY\n", contact_ptr->aor.len, contact_ptr->aor.s); contact_ptr->state = CONTACT_EXPIRE_PENDING_NOTIFY; ref_contact_unsafe(contact_ptr); expired_contacts[num_expired_contacts] = contact_ptr; num_expired_contacts++; } } contact_ptr = contact_ptr->next; } if (contact_list->slot[i].n > n) { n = contact_list->slot[i].n; } unlock_contact_slot_i(i); contact_list->max_collisions = n; if (abort == 1) { break; } } LM_DBG("*** mem_timer_udomain - checking contacts - FINISHED ***\n"); } temp = 0; n = _d->max_collisions; LM_DBG("*** mem_timer_udomain - checking IMPUs - START ***\n"); for (i = istart; i < _d->size; i+=istep) { lock_ulslot(_d, i); ptr = _d->table[i].first; temp = 0; while (ptr) { temp = 1; #ifdef EXTRA_DEBUG LM_DBG("ULSLOT %d LOCKED\n", i); #endif t = ptr; ptr = ptr->next; timer_impurecord(t); } if (temp) { #ifdef EXTRA_DEBUG LM_DBG("ULSLOT %d UN-LOCKED\n", i); #endif } if (_d->table[i].n > n) n = _d->table[i].n; unlock_ulslot(_d, i); _d->max_collisions = n; } LM_DBG("*** mem_timer_udomain - checking IMPUs - FINISHED ***\n"); if (istart == 0) { n = ims_subscription_list->max_collisions; for (i = 0; i < ims_subscription_list->size; i++) { lock_subscription_slot(i); if (ims_subscription_list->slot[i].n > n) { n = ims_subscription_list->slot[i].n; } unlock_subscription_slot(i); } ims_subscription_list->max_collisions = n; /* now we delete the expired contacts. (mark them for deletion */ for (i=0; i<num_expired_contacts; i++) { slot = expired_contacts[i]->sl; lock_contact_slot_i(slot); if (expired_contacts[i]->state != CONTACT_DELAYED_DELETE) { LM_DBG("Setting contact state to CONTACT_DELETED for contact [%.*s]\n", expired_contacts[i]->aor.len, expired_contacts[i]->aor.s); expired_contacts[i]->state = CONTACT_DELETED; unref_contact_unsafe(expired_contacts[i]); } else { LM_DBG("deleting contact [%.*s]\n", expired_contacts[i]->aor.len, expired_contacts[i]->aor.s); delete_scontact(expired_contacts[i]); } unlock_contact_slot_i(slot); } } }