/*! * \brief Write through timer, used for WRITE_THROUGH db_mode * * Write through timer, used for WRITE_THROUGH db_mode. Process all * contacts from the record, delete all expired ones from the DB. * \param _r processed record * \note currently unused, this mode is also handled by the wb_timer */ static inline void wt_timer(urecord_t* _r) { ucontact_t* ptr, *t; ptr = _r->contacts; while(ptr) { if (!VALID_CONTACT(ptr, act_time)) { /* run callbacks for EXPIRE event */ if (exists_ulcb_type(UL_CONTACT_EXPIRE)) { run_ul_callbacks( UL_CONTACT_EXPIRE, ptr); } LM_DBG("Binding '%.*s','%.*s' has expired\n", ptr->aor->len, ZSW(ptr->aor->s), ptr->c.len, ZSW(ptr->c.s)); t = ptr; ptr = ptr->next; if (db_delete_ucontact(t) < 0) { LM_ERR("deleting contact from database failed\n"); } mem_delete_ucontact(_r, t); update_stat( _r->slot->d->expires, 1); } else { ptr = ptr->next; } } }
/*! * \brief Write-back timer, used for WRITE_BACK db_mode * * Write-back timer, used for WRITE_BACK db_mode. Process * all contacts from the record, delete expired ones from the DB. * Furthermore it updates changed contacts, and also insert new * ones in the DB. * \param _r processed record */ static inline void wb_timer(urecord_t* _r) { ucontact_t* ptr, *t; cstate_t old_state; int op; ptr = _r->contacts; while(ptr) { if (!VALID_CONTACT(ptr, act_time)) { /* run callbacks for EXPIRE event */ if (exists_ulcb_type(UL_CONTACT_EXPIRE)) { run_ul_callbacks( UL_CONTACT_EXPIRE, ptr); } LM_DBG("Binding '%.*s','%.*s' has expired\n", ptr->aor->len, ZSW(ptr->aor->s), ptr->c.len, ZSW(ptr->c.s)); update_stat( _r->slot->d->expires, 1); t = ptr; ptr = ptr->next; /* Should we remove the contact from the database ? */ if (st_expired_ucontact(t) == 1) { if (db_delete_ucontact(t) < 0) { LM_ERR("failed to delete contact from the database\n"); } } mem_delete_ucontact(_r, t); } else { /* Determine the operation we have to do */ old_state = ptr->state; op = st_flush_ucontact(ptr); switch(op) { case 0: /* do nothing, contact is synchronized */ break; case 1: /* insert */ if (db_insert_ucontact(ptr) < 0) { LM_ERR("inserting contact into database failed\n"); ptr->state = old_state; } break; case 2: /* update */ if (db_update_ucontact(ptr) < 0) { LM_ERR("updating contact in db failed\n"); ptr->state = old_state; } break; } ptr = ptr->next; } } }
/*! * \brief Delete ucontact from impurecord * \param _r record where the contact belongs to * \param _c deleted contact * \return 0 on success, -1 on failure */ int delete_scontact(struct ucontact* _c) { int ret = 0; LM_DBG("Deleting contact: [%.*s]\n", _c->c.len, _c->c.s); /*DB?*/ if (db_mode == WRITE_THROUGH && db_delete_ucontact(_c) != 0) { LM_ERR("error removing contact from DB [%.*s]... will still remove from memory\n", _c->c.len, _c->c.s); } mem_delete_ucontact(_c); return ret; }
/* * This routine is used when db_mode is * set to WRITE_THROUGH */ static inline int wt_timer(urecord_t* _r) { ucontact_t* ptr, *t; int not = 0; ptr = _r->contacts; while(ptr) { if (!VALID_CONTACT(ptr, act_time)) { /* run callbacks for EXPIRE event */ if (exists_ulcb_type(UL_CONTACT_EXPIRE)) { run_ul_callbacks( UL_CONTACT_EXPIRE, ptr); } notify_watchers(_r, ptr, PRES_OFFLINE); LOG(L_NOTICE, "Binding '%.*s','%.*s' has expired\n", ptr->uid->len, ZSW(ptr->uid->s), ptr->c.len, ZSW(ptr->c.s)); t = ptr; ptr = ptr->next; /* it was the last contact and it was in normal * state, so notify */ if (!ptr && t->state == CS_SYNC) not=1; if (db_delete_ucontact(t) < 0) { LOG(L_ERR, "wt_timer(): Error while deleting contact from " "database\n"); } delete_reg_avps(t); mem_delete_ucontact(_r, t); _r->slot->d->expired++; } else { /* the contact was unregistered and is not marked * for replication so remove it, but the notify was * already done during unregister */ ptr = ptr->next; } } return 0; }
/*! * \brief Delete ucontact from impurecord * \param _r record where the contact belongs to * \param _c deleted contact * \return 0 on success, -1 on failure */ int delete_ucontact(impurecord_t* _r, struct ucontact* _c) { int ret = 0; if (exists_ulcb_type(_c->cbs, UL_CONTACT_DELETE)) { run_ul_callbacks(_c->cbs, UL_CONTACT_DELETE, _r, _c); } if (exists_ulcb_type(_r->cbs, UL_IMPU_DELETE_CONTACT)) { run_ul_callbacks(_r->cbs, UL_IMPU_DELETE_CONTACT, _r, _c); } /*DB?*/ if (db_mode == WRITE_THROUGH && db_delete_ucontact(_r, _c) != 0) { LM_ERR("error removing contact from DB [%.*s]... will still remove from memory\n", _c->c.len, _c->c.s); } mem_delete_ucontact(_r, _c); return ret; }
/*! * \brief Delete ucontact from urecord * \param _r record where the contact belongs to * \param _c deleted contact * \return 0 on success, -1 on failure */ int delete_ucontact(urecord_t* _r, struct ucontact* _c) { int ret = 0; if (exists_ulcb_type(UL_CONTACT_DELETE)) { run_ul_callbacks( UL_CONTACT_DELETE, _c); } if (st_delete_ucontact(_c) > 0) { if (db_mode == WRITE_THROUGH || db_mode==DB_ONLY) { if (db_delete_ucontact(_c) < 0) { LM_ERR("failed to remove contact from database\n"); ret = -1; } } mem_delete_ucontact(_r, _c); } return ret; }
/* * Delete ucontact from urecord */ int delete_ucontact(urecord_t* _r, struct ucontact* _c) { if (exists_ulcb_type(UL_CONTACT_DELETE)) { run_ul_callbacks( UL_CONTACT_DELETE, _c); } notify_watchers(_r, _c, PRES_OFFLINE); if (st_delete_ucontact(_c) > 0) { if (db_mode == WRITE_THROUGH) { if (db_delete_ucontact(_c) < 0) { LOG(L_ERR, "delete_ucontact(): Can't remove contact from " "database\n"); } } delete_reg_avps(_c); mem_delete_ucontact(_r, _c); } return 0; }
/* * Delete ucontact from urecord */ int delete_ucontact(urecord_t* _r, struct ucontact* _c) { struct ucontact* ptr; if (st_delete_ucontact(_c) > 0) { if (db_mode == WRITE_THROUGH) { if (db_delete_ucontact(_c) < 0) { LOG(L_ERR, "delete_ucontact(): Can't remove contact from " "database\n"); } } mem_delete_ucontact(_r, _c); } ptr = _r->contacts; while(ptr) { if (ptr->state < CS_ZOMBIE_N) return 0; ptr = ptr->next; } notify_watchers(_r, PRES_OFFLINE); return 0; }
/*! * \brief Expires timer for NO_DB db_mode * * Expires timer for NO_DB db_mode, process all contacts from * the record, delete the expired ones from memory. * \param _r processed record */ static inline void nodb_timer(impurecord_t* _r) { ucontact_t* ptr, *t; unsigned int hash_code = 0; reg_subscriber *s; subs_t* sub_dialog; get_act_time(); s = _r->shead; LM_DBG("Checking validity of IMPU: <%.*s> registration subscriptions\n", _r->public_identity.len, _r->public_identity.s); while (s) { if (!valid_subscriber(s)) { LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> expired and removed.\n", s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s); delete_subscriber(_r, s); } else { LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> is valid and expires in %d seconds.\n", s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s, (unsigned int) (s->expires - time(NULL))); hash_code = core_hash(&s->call_id, &s->to_tag, sub_dialog_hash_size); LM_DBG("Hash size: <%i>", sub_dialog_hash_size); LM_DBG("Searching sub dialog hash info with call_id: <%.*s> and ttag <%.*s> ftag <%.*s> and hash code <%i>", s->call_id.len, s->call_id.s, s->to_tag.len, s->to_tag.s, s->from_tag.len, s->from_tag.s, hash_code); /* search the record in hash table */ lock_get(&sub_dialog_table[hash_code].lock); sub_dialog= pres_search_shtable(sub_dialog_table, s->call_id, s->to_tag, s->from_tag, hash_code); if(sub_dialog== NULL) { LM_ERR("DBG:registrar_timer: Subscription has no dialog record in hash table\n"); }else { LM_DBG("DBG:registrar_timer: Subscription has dialog record in hash table with presentity uri <%.*s>\n", sub_dialog->pres_uri.len, sub_dialog->pres_uri.s); } lock_release(&sub_dialog_table[hash_code].lock); } s = s->next; } ptr = _r->contacts; LM_DBG("Checking validity of IMPU: <%.*s> contacts\n", _r->public_identity.len, _r->public_identity.s); while (ptr) { if (!VALID_CONTACT(ptr, act_time)) { /* run callbacks for EXPIRE event */ if (exists_ulcb_type(ptr->cbs, UL_CONTACT_EXPIRE)) run_ul_callbacks(ptr->cbs, UL_CONTACT_EXPIRE, _r, ptr); if (exists_ulcb_type(_r->cbs, UL_IMPU_EXPIRE_CONTACT)) { run_ul_callbacks(_r->cbs, UL_IMPU_EXPIRE_CONTACT, _r, ptr); } LM_DBG("Binding '%.*s','%.*s' has expired\n", ptr->aor->len, ZSW(ptr->aor->s), ptr->c.len, ZSW(ptr->c.s)); t = ptr; ptr = ptr->next; if (db_mode == WRITE_THROUGH && db_delete_ucontact(_r, t) != 0) { LM_ERR("error removing contact from DB [%.*s]... will still remove from memory\n", t->c.len, t->c.s); } mem_delete_ucontact(_r, t); update_stat(_r->slot->d->expires, 1); } else { LM_DBG("IMPU:<%.*s> - contact:<%.*s> is valid and expires in %d seconds\n", _r->public_identity.len, _r->public_identity.s, ptr->c.len, ptr->c.s, (unsigned int) (ptr->expires - time(NULL))); ptr = ptr->next; } } }
/* * Write-back timer */ static inline int wb_timer(urecord_t* _r) { ucontact_t* ptr, *t; int op; int not = 0; ptr = _r->contacts; while(ptr) { if (!VALID_CONTACT(ptr, act_time)) { /* run callbacks for EXPIRE event */ if (exists_ulcb_type(UL_CONTACT_EXPIRE)) { run_ul_callbacks( UL_CONTACT_EXPIRE, ptr); } notify_watchers(_r, ptr, PRES_OFFLINE); LOG(L_NOTICE, "Binding '%.*s','%.*s' has expired\n", ptr->uid->len, ZSW(ptr->uid->s), ptr->c.len, ZSW(ptr->c.s)); if (ptr->next == 0) not=1; _r->slot->d->expired++; t = ptr; ptr = ptr->next; /* Should we remove the contact from the database ? */ if (st_expired_ucontact(t) == 1) { if (db_delete_ucontact(t) < 0) { LOG(L_ERR, "wb_timer(): Can't delete contact from the database\n"); } } delete_reg_avps(t); mem_delete_ucontact(_r, t); } else { /* Determine the operation we have to do */ op = st_flush_ucontact(ptr); switch(op) { case 0: /* do nothing, contact is synchronized */ break; case 1: /* insert */ if (db_store_ucontact(ptr) < 0) { LOG(L_ERR, "wb_timer(): Error while inserting contact into database\n"); } break; case 2: /* update */ if (db_store_ucontact(ptr) < 0) { LOG(L_ERR, "wb_timer(): Error while updating contact in db\n"); } break; case 4: /* delete */ if (db_delete_ucontact(ptr) < 0) { LOG(L_ERR, "wb_timer(): Can't delete contact from database\n"); } /* fall through to the next case statement */ case 3: /* delete from memory */ delete_reg_avps(ptr); mem_delete_ucontact(_r, ptr); break; } ptr = ptr->next; } } return 0; }
/* * Write-back timer */ static inline int wb_timer(urecord_t* _r) { ucontact_t* ptr, *t; int op; int not = 0; ptr = _r->contacts; while(ptr) { if (ptr->expires < act_time) { if (ptr->replicate != 0) { LOG(L_NOTICE, "Keeping binding '%.*s','%.*s' for " "replication\n", ptr->aor->len, ZSW(ptr->aor->s), ptr->c.len, ZSW(ptr->c.s)); /* keep it for replication, but it expired normaly * and was the last contact, so notify */ if (!ptr->next && ptr->state < CS_ZOMBIE_N) not=1; ptr = ptr->next; } else { /* state == ZOMBIE the contact was remove by user */ if (ptr->state < CS_ZOMBIE_N) { LOG(L_NOTICE, "Binding '%.*s','%.*s' has expired\n", ptr->aor->len, ZSW(ptr->aor->s), ptr->c.len, ZSW(ptr->c.s)); if (ptr->next == 0) not=1; _r->slot->d->expired++; } t = ptr; ptr = ptr->next; /* Should we remove the contact from the database ? */ if (st_expired_ucontact(t) == 1) { if (db_delete_ucontact(t) < 0) { LOG(L_ERR, "wb_timer(): Can't delete contact from the database\n"); } } mem_delete_ucontact(_r, t); } if (not) notify_watchers(_r, PRES_OFFLINE); } else { /* Determine the operation we have to do */ op = st_flush_ucontact(ptr); switch(op) { case 0: /* do nothing, contact is synchronized */ break; case 1: /* insert */ if (db_insert_ucontact(ptr) < 0) { LOG(L_ERR, "wb_timer(): Error while inserting contact into database\n"); } break; case 2: /* update */ if (db_update_ucontact(ptr) < 0) { LOG(L_ERR, "wb_timer(): Error while updating contact in db\n"); } break; case 3: /* delete from memory */ mem_delete_ucontact(_r, ptr); break; case 4: /* delete */ if (db_delete_ucontact(ptr) < 0) { LOG(L_ERR, "wb_timer(): Can't delete contact from database\n"); } mem_delete_ucontact(_r, ptr); break; } ptr = ptr->next; } } return 0; }
/* * This routine is used when db_mode is * set to WRITE_THROUGH */ static inline int wt_timer(urecord_t* _r) { ucontact_t* ptr, *t; int not = 0; ptr = _r->contacts; while(ptr) { if (ptr->expires < act_time) { if (ptr->replicate != 0) { LOG(L_NOTICE, "Keeping binding '%.*s','%.*s' for " "replication\n", ptr->aor->len, ZSW(ptr->aor->s), ptr->c.len, ZSW(ptr->c.s)); /* keep it for replication, but it expired normaly * and was the last contact, so notify */ if (!ptr->next && ptr->state == CS_SYNC) not=1; ptr = ptr->next; } else { LOG(L_NOTICE, "Binding '%.*s','%.*s' has expired\n", ptr->aor->len, ZSW(ptr->aor->s), ptr->c.len, ZSW(ptr->c.s)); t = ptr; ptr = ptr->next; /* it was the last contact and it was in normal * state, so notify */ if (!ptr && t->state == CS_SYNC) not=1; if (db_delete_ucontact(t) < 0) { LOG(L_ERR, "wt_timer(): Error while deleting contact from " "database\n"); } mem_delete_ucontact(_r, t); _r->slot->d->expired++; } if (not) notify_watchers(_r, PRES_OFFLINE); } else { /* the contact was unregistered and is not marked * for replication so remove it, but the notify was * allready done during unregister */ if (ptr->state == CS_ZOMBIE_S && ptr->replicate == 0) { LOG(L_NOTICE, "removing spare zombie '%.*s','%.*s'\n", ptr->aor->len, ZSW(ptr->aor->s), ptr->c.len, ZSW(ptr->c.s)); t = ptr; ptr = ptr->next; if (db_delete_ucontact(t) < 0) { LOG(L_ERR, "wt_timer(): Error while deleting contact from " "database\n"); } mem_delete_ucontact(_r, t); } else ptr = ptr->next; } } return 0; }