Kaynağa Gözat

Merge pull request #730 from athonet-open/fix_DB_scscf

Improvements on DB handling on S-CSCF usrloc
ng-voice GmbH 9 yıl önce
ebeveyn
işleme
5ef8fa840c

+ 23 - 3
modules/ims_usrloc_scscf/udomain.c

@@ -267,6 +267,7 @@ void mem_timer_udomain(udomain_t* _d, int istart, int istep) {
     time_t now;
     int abort = 0;
     int slot;
+	int ref_count_db;
     
     now = time(0);
     
@@ -297,10 +298,10 @@ void mem_timer_udomain(udomain_t* _d, int istart, int istep) {
                     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: %d)\n", 
+                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,
-                        contact_ptr->state);
+                        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) {
@@ -309,7 +310,26 @@ void mem_timer_udomain(udomain_t* _d, int istart, int istep) {
                             expired_contacts[num_expired_contacts] = contact_ptr;
                             num_expired_contacts++;
                         } else {
-                            LM_DBG("contact in state CONTACT_DELATED_DELETE still has a ref count of [%d]... not doing anything for now\n", contact_ptr->ref_count);
+							/* 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 = 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);

+ 17 - 0
modules/ims_usrloc_scscf/usrloc.h

@@ -377,6 +377,23 @@ static inline char* get_impu_regstate_as_string(enum pi_reg_states reg_state) {
     }
 }
 
+static inline char* get_contact_state_as_string(enum contact_state c_state) {
+    switch(c_state) {
+        case CONTACT_VALID:
+            return "Contact valid";
+        case CONTACT_DELETE_PENDING:
+            return "Contact in delete pending";
+        case CONTACT_EXPIRE_PENDING_NOTIFY:
+            return "Contact expired with pending NOTIFY";
+        case CONTACT_DELETED:
+            return "Contact deleted";
+        case CONTACT_DELAYED_DELETE:
+            return "Contact with delayed delete";
+        default:
+            return "unknown";
+    }
+}
+
 typedef struct _contact_ptr {
     ucontact_t* contact;
     struct contact_ptr* prev;

+ 125 - 59
modules/ims_usrloc_scscf/usrloc_db.c

@@ -65,6 +65,9 @@ str subscriber_id_col = str_init(SUBSCRIBER_ID_COL);
 str query_buffer 		= { 0, 0 };
 int query_buffer_len		= 0;
 
+char* check_contact_links_query = "SELECT * FROM impu_contact WHERE contact_id = (SELECT contact.id from contact WHERE contact.contact='%.*s')";
+int check_contact_links_query_len;
+
 char* impu_contact_insert_query = "INSERT INTO impu_contact (impu_id, contact_id) (SELECT I.id, C.id FROM impu I, contact C WHERE I.impu='%.*s' and C.contact='%.*s')";
 int impu_contact_insert_query_len;
 char* impu_contact_delete_query = "DELETE impu_contact FROM impu_contact INNER JOIN impu ON impu_contact.impu_id = impu.id INNER JOIN contact ON contact.id = impu_contact.contact_id where impu.impu = '%.*s' and contact.contact = '%.*s'";
@@ -75,6 +78,9 @@ int impu_subscriber_insert_query_len;
 char* impu_subscriber_delete_query = "DELETE impu_subscriber FROM impu_subscriber INNER JOIN impu on impu_subscriber.impu_id=impu.id INNER JOIN subscriber on impu_subscriber.subscriber_id=subscriber.id WHERE impu.impu='%.*s' AND subscriber.event='%.*s' and subscriber.watcher_contact='%.*s' and subscriber.presentity_uri='%.*s'";
 int impu_subscriber_delete_query_len;
 
+char* delete_unlinked_contact_query = "DELETE from contact";
+int delete_unlinked_contact_query_len;
+
 
 
 extern db1_con_t* ul_dbh;
@@ -147,7 +153,7 @@ int db_insert_impurecord(struct udomain* _d, str* public_identity,
 	db_key_t key[8];
 	db_val_t val[8];
 	str bin_str;
-	
+
 	LM_DBG("DB: Inserting/Updating IMPU [%.*s]\n", public_identity->len, public_identity->s);
 
 	//serialise ims_subscription
@@ -217,7 +223,7 @@ int db_insert_impurecord(struct udomain* _d, str* public_identity,
 	} else {
 	    val[i].nul = 1;
 	}
-	
+
 	i++;
 
 	if (ul_dbf.use_table(ul_dbh, &impu_table) != 0) {
@@ -230,7 +236,7 @@ int db_insert_impurecord(struct udomain* _d, str* public_identity,
 		bin_free(&x);
 		return -1;
 	}
-	
+
 	if (s)
 	    bin_free(&x);
 
@@ -240,7 +246,7 @@ int db_insert_impurecord(struct udomain* _d, str* public_identity,
 int db_delete_impurecord(udomain_t* _d, struct impurecord* _r) {
 	db_key_t key[1];
 	db_val_t val[1];
-	
+
 	LM_DBG("DB: deleting IMPU [%.*s]\n", _r->public_identity.len, _r->public_identity.s);
 
 	key[0] = &impu_col;
@@ -256,7 +262,7 @@ int db_delete_impurecord(udomain_t* _d, struct impurecord* _r) {
 		LM_ERR("Unable to delete impu [%.*s] from DB\n", _r->public_identity.len, _r->public_identity.s);
 		return -1;
 	}
-	
+
 	return 0;
 }
 
@@ -265,7 +271,7 @@ static str param_name_and_nody = {"%.*s=%.*s;", 1};
 static str param_name_no_body = {"%.*s;", 1};
 
 int db_insert_ucontact(impurecord_t* _r, ucontact_t* _c) {
-	
+
 	str param_buf, param_pad;
 	param_t * tmp;
 	char param_bufc[MAX_PARAMS_SIZE], param_padc[MAX_PARAMS_SIZE];
@@ -273,12 +279,12 @@ int db_insert_ucontact(impurecord_t* _r, ucontact_t* _c) {
 	param_buf.len = 0;
 	param_pad.s = param_padc;
 	param_pad.len = 0;
-	
+
 	db_key_t key[7];
 	db_val_t val[7];
-	
+
 	LM_DBG("DB: inserting ucontact [%.*s]\n", _c->c.len, _c->c.s);
-	
+
 	tmp = _c->params;
 	while (tmp) {
 	    if(tmp->body.len > 0) {
@@ -291,7 +297,7 @@ int db_insert_ucontact(impurecord_t* _r, ucontact_t* _c) {
 	    tmp = tmp->next;
 	}
 	LM_DBG("Converted params to string to insert into db: [%.*s]\n", param_buf.len, param_buf.s);
-	
+
 
 	key[0] = &contact_col;
 	key[1] = &params_col;
@@ -308,7 +314,7 @@ int db_insert_ucontact(impurecord_t* _r, ucontact_t* _c) {
 	val[1].type = DB1_STR;
 	val[1].nul = 0;
 	val[1].val.str_val = param_buf;
-	
+
 	val[2].type = DB1_STR;
 	val[2].nul = 0;
 	val[2].val.str_val = _c->path;
@@ -368,9 +374,9 @@ int db_insert_subscriber(impurecord_t* _r, reg_subscriber* _reg_subscriber) {
 	int col_num = 12;
 	db_key_t key[col_num];
 	db_val_t val[col_num];
-	
+
 	LM_DBG("DB: inserting subscriber [%.*s]\n", _reg_subscriber->presentity_uri.len, _reg_subscriber->presentity_uri.s);
-	
+
 	key[0] = &sub_watcher_uri_col;
 	key[1] = &sub_watcher_contact_col;
 	key[2] = &sub_presentity_uri_col;
@@ -407,31 +413,31 @@ int db_insert_subscriber(impurecord_t* _r, reg_subscriber* _reg_subscriber) {
 	val[5].type = DB1_INT;
 	val[5].nul = 0;
 	val[5].val.int_val = _reg_subscriber->version;
-	
+
 	val[6].type = DB1_INT;
 	val[6].nul = 0;
 	val[6].val.int_val = _reg_subscriber->local_cseq;
-	
+
 	val[7].type = DB1_STR;
 	val[7].nul = 0;
 	val[7].val.str_val = _reg_subscriber->call_id;
-	
+
 	val[8].type = DB1_STR;
 	val[8].nul = 0;
 	val[8].val.str_val = _reg_subscriber->from_tag;
-	
+
 	val[9].type = DB1_STR;
 	val[9].nul = 0;
 	val[9].val.str_val = _reg_subscriber->to_tag;
-	
+
 	val[10].type = DB1_STR;
 	val[10].nul = 0;
 	val[10].val.str_val = _reg_subscriber->record_route;
-	
+
 	val[11].type = DB1_STR;
 	val[11].nul = 0;
 	val[11].val.str_val = _reg_subscriber->sockinfo_str;
-	
+
 	if (ul_dbf.use_table(ul_dbh, &subscriber_table) != 0) {
 		LM_ERR("Unable to use table [%.*s]\n", subscriber_table.len, subscriber_table.s);
 		return -1;
@@ -440,7 +446,7 @@ int db_insert_subscriber(impurecord_t* _r, reg_subscriber* _reg_subscriber) {
 		LM_ERR("Failed to insert/update subscriber record for [%.*s]\n", _reg_subscriber->presentity_uri.len, _reg_subscriber->presentity_uri.s);
 		return -1;
 	}
-	
+
 	return 0;
 }
 
@@ -448,7 +454,7 @@ int db_insert_subscriber(impurecord_t* _r, reg_subscriber* _reg_subscriber) {
 int db_delete_subscriber(impurecord_t* _r, reg_subscriber* _reg_subscriber) {
 	db_key_t key[3];
 	db_val_t val[3];
-	
+
 	LM_DBG("Deleting subscriber binding [%.*s] on impu [%.*s]\n",
 			_reg_subscriber->presentity_uri.len, _reg_subscriber->presentity_uri.s,
 			_r->public_identity.len, _r->public_identity.s);
@@ -462,24 +468,24 @@ int db_delete_subscriber(impurecord_t* _r, reg_subscriber* _reg_subscriber) {
 	val[0].type = DB1_INT;
 	val[0].nul = 0;
 	val[0].val.int_val = _reg_subscriber->event;
-		
+
 	key[1] = &sub_watcher_contact_col;
 	val[1].type = DB1_STR;
 	val[1].nul = 0;
 	val[1].val.str_val = _reg_subscriber->watcher_contact;
-	
+
 	key[2] = &sub_presentity_uri_col;
 	val[2].type = DB1_STR;
 	val[2].nul = 0;
 	val[2].val.str_val = _reg_subscriber->presentity_uri;
-	
+
 	if (ul_dbf.delete(ul_dbh, key, 0, val, 3) != 0) {
 		LM_ERR("Unable to delete subscriber [%.*s] from DB\n", _reg_subscriber->presentity_uri.len, _reg_subscriber->presentity_uri.s);
 		return -1;
 	}
-	
+
 	return 0;
-	
+
 }
 
 
@@ -510,7 +516,7 @@ int inline int_to_str_len(int i) {
 static inline int dbrow2contact(db_val_t* val, ucontact_info_t* ci) {
 	static str path, user_agent, callid, params;
 	param_hooks_t hooks;
-	
+
 	// Set ci to 0:
 	memset( ci, 0, sizeof(ucontact_info_t));
 
@@ -522,7 +528,7 @@ static inline int dbrow2contact(db_val_t* val, ucontact_info_t* ci) {
 			LM_WARN("Error while parsing parameters: %.*s\n", params.len, params.s);
 		}
 	}
-	
+
 	/* path */
 	if (!VAL_NULL(val + 2)) {
 		path.s = (char*)VAL_STRING(val + 2);
@@ -559,7 +565,7 @@ static inline int dbrow2contact(db_val_t* val, ucontact_info_t* ci) {
 
 static inline int dbrow2subscriber(db_val_t* val, subscriber_data_t* subscriber_data) {
 	static str presentity_uri, watcher_uri, watcher_contact, call_id, from_tag, to_tag, record_route, sockinfo_str;
-	
+
 	/*presentity uri*/
 	if (!VAL_NULL(val)) {
 	    presentity_uri.s = (char*) VAL_STRING(val);
@@ -567,7 +573,7 @@ static inline int dbrow2subscriber(db_val_t* val, subscriber_data_t* subscriber_
 	}
 	subscriber_data->presentity_uri = &presentity_uri;
 	LM_DBG("presentity_uri: [%.*s]", subscriber_data->presentity_uri->len, subscriber_data->presentity_uri->s);
-	
+
 	/*watcher_uri*/
 	if (!VAL_NULL(val + 1)) {
 	    watcher_uri.s = (char*) VAL_STRING(val + 1);
@@ -575,7 +581,7 @@ static inline int dbrow2subscriber(db_val_t* val, subscriber_data_t* subscriber_
 	}
 	subscriber_data->watcher_uri = &watcher_uri;
 	LM_DBG("watcher_uri: [%.*s]", subscriber_data->watcher_uri->len, subscriber_data->watcher_uri->s);
-	
+
 	/*watcher_contact*/
 	if (!VAL_NULL(val + 2)) {
 	    watcher_contact.s = (char*) VAL_STRING(val + 2);
@@ -583,31 +589,31 @@ static inline int dbrow2subscriber(db_val_t* val, subscriber_data_t* subscriber_
 	}
 	subscriber_data->watcher_contact = &watcher_contact;
 	LM_DBG("watcher_contact: [%.*s]", subscriber_data->watcher_contact->len, subscriber_data->watcher_contact->s);
-	
+
 	/*event*/
 	if (!VAL_NULL(val + 3)) {
 	    subscriber_data->event = VAL_INT(val + 3);
 	}
 	LM_DBG("event: [%d]", subscriber_data->event);
-	
+
 	/* expires */
 	if (!VAL_NULL(val + 4)) {
 		subscriber_data->expires = VAL_TIME(val + 4);
 	}
 	LM_DBG("expires: [%d]", subscriber_data->expires);
-	
+
 	/*event*/
 	if (!VAL_NULL(val + 5)) {
 	    subscriber_data->version = VAL_INT(val + 5);
 	}
 	LM_DBG("version: [%d]", subscriber_data->version);
-	
+
 	/*local_cseq*/
 	if (!VAL_NULL(val + 6)) {
 	    subscriber_data->local_cseq = VAL_INT(val + 6);
 	}
 	LM_DBG("local_cseq: [%d]", subscriber_data->local_cseq);
-	
+
 	/* callid */
 	if (!VAL_NULL(val + 7)) {
 		call_id.s = (char*) VAL_STRING(val + 7);
@@ -615,7 +621,7 @@ static inline int dbrow2subscriber(db_val_t* val, subscriber_data_t* subscriber_
 	}
 	subscriber_data->callid = &call_id;
 	LM_DBG("callid: [%.*s]", subscriber_data->callid->len, subscriber_data->callid->s);
-	
+
 	/* ftag */
 	if (!VAL_NULL(val + 8)) {
 		from_tag.s = (char*) VAL_STRING(val + 8);
@@ -623,7 +629,7 @@ static inline int dbrow2subscriber(db_val_t* val, subscriber_data_t* subscriber_
 	}
 	subscriber_data->ftag = &from_tag;
 	LM_DBG("ftag: [%.*s]", subscriber_data->ftag->len, subscriber_data->ftag->s);
-	
+
 	/* ttag */
 	if (!VAL_NULL(val + 9)) {
 		to_tag.s = (char*) VAL_STRING(val + 9);
@@ -631,7 +637,7 @@ static inline int dbrow2subscriber(db_val_t* val, subscriber_data_t* subscriber_
 	}
 	subscriber_data->ttag = &to_tag;
 	LM_DBG("ttag: [%.*s]", subscriber_data->ttag->len, subscriber_data->ttag->s);
-	
+
 	/* record_route */
 	if (!VAL_NULL(val + 10)) {
 		record_route.s = (char*) VAL_STRING(val + 10);
@@ -639,7 +645,7 @@ static inline int dbrow2subscriber(db_val_t* val, subscriber_data_t* subscriber_
 	}
 	subscriber_data->record_route = &record_route;
 	LM_DBG("record_route: [%.*s]", subscriber_data->record_route->len, subscriber_data->record_route->s);
-	
+
 	/* sockinfo_str */
 	if (!VAL_NULL(val + 11)) {
 		sockinfo_str.s = (char*) VAL_STRING(val + 11);
@@ -647,7 +653,33 @@ static inline int dbrow2subscriber(db_val_t* val, subscriber_data_t* subscriber_
 	}
 	subscriber_data->sockinfo_str = &sockinfo_str;
 	LM_DBG("sockinfo_str: [%.*s]", subscriber_data->sockinfo_str->len, subscriber_data->sockinfo_str->s);
-	
+
+	return 0;
+}
+
+int delete_all_unlinked_contacts() {
+	int len;
+	db1_res_t* rs;
+
+	len = strlen(delete_unlinked_contact_query) +1;
+	if (!query_buffer_len || query_buffer_len < len) {
+		if (query_buffer.s) {
+			pkg_free(query_buffer.s);
+		}
+		query_buffer.s = (char*) pkg_malloc(len);
+		if (!query_buffer.s) {
+			LM_ERR("no more pkg mem\n");
+			return -1;
+		}
+		query_buffer_len = len;
+	}
+	snprintf(query_buffer.s,query_buffer_len,"%s",delete_unlinked_contact_query);
+	query_buffer.len = strlen(query_buffer.s);
+
+	if (ul_dbf.raw_query(ul_dbh, &query_buffer, &rs) != 0) {
+		return -1;
+	}
+	ul_dbf.free_result(ul_dbh,rs);
 	return 0;
 }
 
@@ -717,9 +749,12 @@ int preload_udomain(db1_con_t* _c, udomain_t* _d) {
     }
 
     if (RES_ROW_N(rs) == 0) {
-	LM_DBG("table is empty\n");
-	ul_dbf.free_result(_c, rs);
-	return 0;
+		LM_DBG("IMPU table is empty, removing all unlinked contacts \n");
+		ul_dbf.free_result(_c, rs);
+		if (delete_all_unlinked_contacts() != 0) {
+			LM_ERR("Not able to delete unlinked contacts\n");
+		}
+		return 0;
     }
 
     LM_DBG("preloading S-CSCF usrloc...\n");
@@ -783,7 +818,7 @@ int preload_udomain(db1_con_t* _c, udomain_t* _d) {
 	    if (!VAL_NULL(vals + 8)) {
 		impu_id = VAL_INT(vals + 8);
 	    }
-		
+
 		int leave_slot_locked = 1;
 		int res = get_subscription(&subscription->private_identity, &found_subscription, leave_slot_locked); //leave slot locked in case we need to add.... don't want racing adds
         if (res != 0) {
@@ -804,7 +839,7 @@ int preload_udomain(db1_con_t* _c, udomain_t* _d) {
 			ref_subscription_unsafe(subscription);	/*assume we will add to impu - if not, we will unref it*/
 			unlock_subscription_slot(subscription->sl);
         }
-		
+
 	    /* insert impu into memory */
 	    lock_udomain(_d, &impu);
 	    if (get_impurecord_unsafe(_d, &impu, &impurecord) != 0) {
@@ -869,14 +904,14 @@ int preload_udomain(db1_con_t* _c, udomain_t* _d) {
 				contact.s = (char*) VAL_STRING(contact_vals);
 				contact.len = strlen(contact.s);
 			    }
-                            
+
                             if (contact.len <=0 || !contact.s){
                                    LM_ERR("Unable to insert contact [%.*s] for IMPU [%.*s] into memory... continuing...\n",
 					    contact.len, contact.s,
-					    impu.len, impu.s); 
+					    impu.len, impu.s);
                                    continue;
                             }
-                            
+
 			    if (dbrow2contact(contact_vals, &contact_data) != 0) {
 				LM_ERR("unable to convert contact row from DB into valid data... moving on\n");
 				continue;
@@ -1025,7 +1060,7 @@ int db_link_contact_to_impu(impurecord_t* _r, ucontact_t* _c) {
 	    return -1;
 	}
 	query_buffer_len = len;
-	
+
     }
 
     snprintf(query_buffer.s, query_buffer_len, impu_contact_insert_query, _r->public_identity.len, _r->public_identity.s, _c->c.len, _c->c.s);
@@ -1042,6 +1077,37 @@ int db_link_contact_to_impu(impurecord_t* _r, ucontact_t* _c) {
     return 0;
 }
 
+int db_check_if_contact_is_linked(ucontact_t* _c) {
+	int len;
+	db1_res_t* rs;
+	int n_res_row = 0;
+
+	len = strlen(check_contact_links_query) + _c->c.len + 1;
+
+	if (!query_buffer_len || query_buffer_len < len) {
+		if (query_buffer.s) {
+			pkg_free(query_buffer.s);
+		}
+		query_buffer.s = (char*) pkg_malloc(len);
+		if (!query_buffer.s) {
+			LM_ERR("no more pkg mem\n");
+			return -1;
+		}
+		query_buffer_len = len;
+
+	}
+
+	snprintf(query_buffer.s,query_buffer_len,check_contact_links_query,_c->c.len,_c->c.s);
+	query_buffer.len = strlen(query_buffer.s);
+	if (ul_dbf.raw_query(ul_dbh, &query_buffer, &rs) != 0) {
+		LM_ERR("Unable to query DB to check if contact[%.*s] is linked\n", _c->c.len, _c->c.s);
+		return -1;
+	}
+	n_res_row = RES_ROW_N(rs);
+	ul_dbf.free_result(ul_dbh, rs);
+	return n_res_row;
+}
+
 int db_unlink_contact_from_impu(impurecord_t* _r, ucontact_t* _c) {
     int len;
     db1_res_t* rs;
@@ -1060,7 +1126,7 @@ int db_unlink_contact_from_impu(impurecord_t* _r, ucontact_t* _c) {
 	    return -1;
 	}
 	query_buffer_len = len;
-	
+
     }
 
     snprintf(query_buffer.s, query_buffer_len, impu_contact_delete_query, _r->public_identity.len, _r->public_identity.s, _c->c.len, _c->c.s);
@@ -1083,7 +1149,7 @@ int db_unlink_subscriber_from_impu(impurecord_t* _r, reg_subscriber* _reg_subscr
     int event_len;
 
     LM_DBG("DB: un-linking subscriber to IMPU\n");
-    
+
     event_len = int_to_str_len(_reg_subscriber->event);
     snprintf(event, event_len + 1, "%d", _reg_subscriber->event);
 
@@ -1099,10 +1165,10 @@ int db_unlink_subscriber_from_impu(impurecord_t* _r, reg_subscriber* _reg_subscr
 	    return -1;
 	}
 	query_buffer_len = len;
-	
+
     }
 
-    snprintf(query_buffer.s, query_buffer_len, impu_subscriber_delete_query, _r->public_identity.len, _r->public_identity.s, strlen(event), event, 
+    snprintf(query_buffer.s, query_buffer_len, impu_subscriber_delete_query, _r->public_identity.len, _r->public_identity.s, strlen(event), event,
 	    _reg_subscriber->watcher_contact.len, _reg_subscriber->watcher_contact.s, _reg_subscriber->presentity_uri.len, _reg_subscriber->presentity_uri.s);
     query_buffer.len = strlen(query_buffer.s);//len;
 
@@ -1121,9 +1187,9 @@ int db_link_subscriber_to_impu(impurecord_t* _r, reg_subscriber* _reg_subscriber
     db1_res_t* rs;
     char event[11];
     int event_len;
-    
+
     LM_DBG("DB: linking subscriber to IMPU\n");
-    
+
     event_len = int_to_str_len(_reg_subscriber->event);
     snprintf(event, event_len + 1, "%d", _reg_subscriber->event);
 
@@ -1139,10 +1205,10 @@ int db_link_subscriber_to_impu(impurecord_t* _r, reg_subscriber* _reg_subscriber
 	    return -1;
 	}
 	query_buffer_len = len;
-	
+
     }
 
-    snprintf(query_buffer.s, query_buffer_len, impu_subscriber_insert_query, _r->public_identity.len, _r->public_identity.s, strlen(event), event, 
+    snprintf(query_buffer.s, query_buffer_len, impu_subscriber_insert_query, _r->public_identity.len, _r->public_identity.s, strlen(event), event,
 	    _reg_subscriber->watcher_contact.len, _reg_subscriber->watcher_contact.s, _reg_subscriber->presentity_uri.len, _reg_subscriber->presentity_uri.s);
     query_buffer.len = strlen(query_buffer.s);//len;
 

+ 2 - 0
modules/ims_usrloc_scscf/usrloc_db.h

@@ -77,4 +77,6 @@ int db_link_subscriber_to_impu(impurecord_t* _r, reg_subscriber* _reg_subscriber
 
 int preload_udomain(db1_con_t* _c, udomain_t* _d);
 
+int db_check_if_contact_is_linked(ucontact_t* _c);
+
 #endif /* USRLOC_DB_H_ */