Browse code

modules/ims_usrloc_scscf: added DB storage for S-CSCF usrloc - currently support NO_DB and DB_WRITETHROUGH

Jason Penton authored on 19/02/2014 18:01:23
Showing 9 changed files
... ...
@@ -56,6 +56,7 @@
56 56
 #include "usrloc.h"
57 57
 #include "bin_utils.h"
58 58
 #include "subscribe.h"
59
+#include "usrloc_db.h"
59 60
 #include "../../lib/ims/useful_defs.h"
60 61
 
61 62
 /*! contact matching mode */
... ...
@@ -66,6 +67,7 @@ int cseq_delay = 20;
66 67
 extern int unreg_validity;
67 68
 extern int maxcontact_behaviour;
68 69
 extern int maxcontact;
70
+extern int db_mode;
69 71
 
70 72
 extern int sub_dialog_hash_size;
71 73
 extern shtable_t sub_dialog_table;
... ...
@@ -391,6 +393,10 @@ static inline void nodb_timer(impurecord_t* _r) {
391 393
             t = ptr;
392 394
             ptr = ptr->next;
393 395
 
396
+			if (db_mode == WRITE_THROUGH && db_delete_ucontact(_r, t) != 0) {
397
+				LM_ERR("error removing contact from DB [%.*s]... will still remove from memory\n", t->c.len, t->c.s);
398
+			}
399
+
394 400
             mem_delete_ucontact(_r, t);
395 401
             update_stat(_r->slot->d->expires, 1);
396 402
         } else {
... ...
@@ -454,6 +460,12 @@ int insert_ucontact(impurecord_t* _r, str* _contact, ucontact_info_t* _ci, ucont
454 460
         return -1;
455 461
     }
456 462
 
463
+    /*DB?*/
464
+	if (db_mode == WRITE_THROUGH && db_insert_ucontact(_r, *_c) != 0) {
465
+		LM_ERR("error inserting contact into db");
466
+		return -1;
467
+	}
468
+
457 469
     if (exists_ulcb_type(NULL, UL_CONTACT_INSERT)) {
458 470
         run_ul_callbacks(NULL, UL_CONTACT_INSERT, _r, *_c);
459 471
     }
... ...
@@ -480,7 +492,11 @@ int delete_ucontact(impurecord_t* _r, struct ucontact* _c) {
480 492
         run_ul_callbacks(_r->cbs, UL_IMPU_DELETE_CONTACT, _r, _c);
481 493
     }
482 494
 
483
-    
495
+	/*DB?*/
496
+	if (db_mode == WRITE_THROUGH && db_delete_ucontact(_r, _c) != 0) {
497
+		LM_ERR("error removing contact from DB [%.*s]... will still remove from memory\n", _c->c.len, _c->c.s);
498
+
499
+	}
484 500
 
485 501
     mem_delete_ucontact(_r, _c);
486 502
 
... ...
@@ -126,14 +126,6 @@ void mem_delete_ucontact(impurecord_t* _r, ucontact_t* _c);
126 126
 void timer_impurecord(impurecord_t* _r);
127 127
 
128 128
 
129
-/*!
130
- * \brief Delete a record from the database
131
- * \param _r deleted record
132
- * \return 0 on success, -1 on failure
133
- */
134
-int db_delete_impurecord(impurecord_t* _r);
135
-
136
-
137 129
 /* ===== Module interface ======== */
138 130
 
139 131
 
... ...
@@ -96,31 +96,6 @@ void print_ucontact(FILE* _f, ucontact_t* _c);
96 96
 int mem_update_ucontact(ucontact_t* _c, ucontact_info_t *_ci);
97 97
 
98 98
 
99
-/* ==== Database related functions ====== */
100
-
101
-/*!
102
- * \brief Insert contact into the database
103
- * \param _c inserted contact
104
- * \return 0 on success, -1 on failure
105
- */
106
-int db_insert_ucontact(ucontact_t* _c);
107
-
108
-
109
-/*!
110
- * \brief Update contact in the database
111
- * \param _c updated contact
112
- * \return 0 on success, -1 on failure
113
- */
114
-int db_update_ucontact(ucontact_t* _c);
115
-
116
-
117
-/*!
118
- * \brief Delete contact from the database
119
- * \param _c deleted contact
120
- * \return 0 on success, -1 on failure
121
- */
122
-int db_delete_ucontact(ucontact_t* _c);
123
-
124 99
 /* ====== Module interface ====== */
125 100
 
126 101
 /*!
... ...
@@ -64,8 +64,10 @@
64 64
 #include "utime.h"
65 65
 #include "usrloc.h"
66 66
 #include "bin_utils.h"
67
+#include "usrloc_db.h"
67 68
 
68 69
 extern int unreg_validity;
70
+extern int db_mode;
69 71
 
70 72
 #ifdef STATISTICS
71 73
 static char *build_stat_name( str* domain, char *var_name)
... ...
@@ -328,7 +330,7 @@ void mem_timer_udomain(udomain_t* _d)
328 330
 				//remove it - housekeeping - not sure why its still here...?
329 331
 				if (exists_ulcb_type(t->cbs, UL_IMPU_NR_DELETE))
330 332
 					run_ul_callbacks(t->cbs, UL_IMPU_NR_DELETE, t, NULL);
331
-				mem_delete_impurecord(_d, t);
333
+					delete_impurecord(_d, &t->public_identity, t);
332 334
 			} else if (t->reg_state == IMPU_UNREGISTERED) {//Remove IMPU record if it is in state IMPU_UNREGISTERED and has expired
333 335
 			    
334 336
 				if (time_now >= t->expires) {//check here and only remove if no subscribes - if there is a subscribe then bump the validity by unreg_validity
... ...
@@ -338,7 +340,7 @@ void mem_timer_udomain(udomain_t* _d)
338 340
 				    } else {
339 341
 					if (exists_ulcb_type(t->cbs, UL_IMPU_UNREG_EXPIRED))
340 342
 						run_ul_callbacks(t->cbs, UL_IMPU_UNREG_EXPIRED, t, NULL);
341
-					mem_delete_impurecord(_d, t);
343
+					delete_impurecord(_d, &t->public_identity, t);
342 344
 				    }
343 345
 				}
344 346
 			//} else if (t->reg_state != IMPU_UNREGISTERED && t->contacts == 0) { /* Remove the entire record if it is empty IFF it is not an UNREGISTERED RECORD */
... ...
@@ -382,7 +384,7 @@ void mem_timer_udomain(udomain_t* _d)
382 384
 					//now run a normal callback on our
383 385
 					if (exists_ulcb_type(t->cbs, UL_IMPU_REG_NC_DELETE))
384 386
 						run_ul_callbacks(t->cbs, UL_IMPU_REG_NC_DELETE, t, NULL);
385
-					mem_delete_impurecord(_d, t);
387
+						delete_impurecord(_d, &t->public_identity, t);
386 388
 				}
387 389
 			}
388 390
 		}
... ...
@@ -479,6 +481,13 @@ int insert_impurecord(struct udomain* _d, str* public_identity, int reg_state, i
479 481
         LM_ERR("inserting record failed\n");
480 482
         goto error;
481 483
     }
484
+
485
+    /*DB?*/
486
+	if (db_mode == WRITE_THROUGH && db_insert_impurecord(_d, public_identity, reg_state, barring, s, ccf1, ccf2, ecf1, ecf2, _r) != 0) {
487
+		LM_ERR("error inserting contact into db");
488
+		goto error;
489
+	}
490
+
482 491
     return 0;
483 492
 
484 493
 error:
... ...
@@ -550,6 +559,13 @@ int delete_impurecord(udomain_t* _d, str* _aor, struct impurecord* _r)
550 559
 	        run_ul_callbacks(_r->cbs, UL_IMPU_DELETE, _r, 0);
551 560
 	}
552 561
 
562
+	/*DB?*/
563
+	if (db_mode == WRITE_THROUGH
564
+			&& db_delete_impurecord(_d, _r) != 0) {
565
+		LM_ERR("error inserting contact into db");
566
+		return 0;
567
+	}
568
+
553 569
 	mem_delete_impurecord(_d, _r);
554 570
 	return 0;
555 571
 }
... ...
@@ -639,3 +655,4 @@ int get_impus_from_subscription_as_string(udomain_t* _d, impurecord_t* impu_rec,
639 655
 
640 656
 	return 0;
641 657
 }
658
+
... ...
@@ -59,6 +59,7 @@
59 59
 #include "ul_callback.h"
60 60
 #include "usrloc.h"
61 61
 #include "hslot_sp.h"
62
+#include "usrloc_db.h"
62 63
 
63 64
 #include "../presence/bind_presence.h"
64 65
 #include "../presence/hash.h"
... ...
@@ -95,6 +96,11 @@ int ul_fetch_rows = 2000;				/*!< number of rows to fetch from result */
95 96
 int ul_hash_size = 9;
96 97
 int subs_hash_size = 9;					/*!<number of ims subscription slots*/
97 98
 
99
+int db_mode = 0;						/*!<database mode*/
100
+db1_con_t* ul_dbh = 0;
101
+db_func_t ul_dbf;
102
+str db_url          = str_init(DEFAULT_DB_URL);	/*!< Database URL */
103
+
98 104
 /* flags */
99 105
 unsigned int nat_bflag = (unsigned int)-1;
100 106
 unsigned int init_flag = 0;
... ...
@@ -137,9 +143,11 @@ static param_export_t params[] = {
137 143
     {"user_data_xsd",     	STR_PARAM, &scscf_user_data_xsd},
138 144
     {"support_wildcardPSI",	INT_PARAM, &scscf_support_wildcardPSI},
139 145
     {"unreg_validity",		INT_PARAM, &unreg_validity},
140
-    {"maxcontact_behaviour", INT_PARAM, &maxcontact_behaviour},
146
+    {"maxcontact_behaviour",INT_PARAM, &maxcontact_behaviour},
141 147
     {"maxcontact",			INT_PARAM, &maxcontact},
142
-    {"sub_dialog_hash_size", INT_PARAM, &sub_dialog_hash_size},
148
+    {"sub_dialog_hash_size",INT_PARAM, &sub_dialog_hash_size},
149
+    {"db_mode",				INT_PARAM, &db_mode},
150
+    {"db_url", 				STR_PARAM, &db_url.s},
143 151
 	{0, 0, 0}
144 152
 };
145 153
 
... ...
@@ -196,6 +204,8 @@ static int mod_init(void) {
196 204
 		return -1;
197 205
 	}
198 206
 
207
+	db_url.len = strlen(db_url.s);
208
+
199 209
 	/* Compute the lengths of string parameters */
200 210
 	usrloc_debug_file.len = strlen(usrloc_debug_file.s);
201 211
 
... ...
@@ -275,6 +285,24 @@ static int mod_init(void) {
275 285
 		return -1;
276 286
 	}
277 287
 
288
+	/* Shall we use database ? */
289
+	if (db_mode != NO_DB) { /* Yes */
290
+		if (db_bind_mod(&db_url, &ul_dbf) < 0) { /* Find database module */
291
+			LM_ERR("failed to bind database module\n");
292
+			return -1;
293
+		}
294
+		if (!DB_CAPABILITY(ul_dbf, DB_CAP_ALL)) {
295
+			LM_ERR("database module does not implement all functions"
296
+					" needed by the module\n");
297
+			return -1;
298
+		}
299
+		if (ul_fetch_rows <= 0) {
300
+			LM_ERR("invalid fetch_rows number '%d'\n", ul_fetch_rows);
301
+			return -1;
302
+		}
303
+	}
304
+
305
+
278 306
 	/* Register cache timer */
279 307
 	register_timer(timer, 0, timer_interval);
280 308
 
... ...
@@ -301,6 +329,38 @@ static int mod_init(void) {
301 329
 
302 330
 static int child_init(int rank)
303 331
 {
332
+	dlist_t* ptr;
333
+
334
+	/* connecting to DB ? */
335
+	switch (db_mode) {
336
+	case NO_DB:
337
+		return 0;
338
+	case WRITE_THROUGH:
339
+		/* we need connection from working SIP and TIMER and MAIN
340
+		 * processes only */
341
+		if (rank <= 0 && rank != PROC_TIMER && rank != PROC_MAIN)
342
+			return 0;
343
+		break;
344
+	}
345
+
346
+	ul_dbh = ul_dbf.init(&db_url); /* Get a database connection per child */
347
+	if (!ul_dbh) {
348
+		LM_ERR("child(%d): failed to connect to database\n", rank);
349
+		return -1;
350
+	}
351
+
352
+	/* _rank==PROC_SIPINIT is used even when fork is disabled */
353
+	if (rank == PROC_SIPINIT && db_mode != DB_ONLY) {
354
+		/* if cache is used, populate from DB */
355
+		for (ptr = root; ptr; ptr = ptr->next) {
356
+			if (preload_udomain(ul_dbh, ptr->d) < 0) {
357
+				LM_ERR("child(%d): failed to preload domain '%.*s'\n",
358
+						rank, ptr->name.len, ZSW(ptr->name.s));
359
+				return -1;
360
+			}
361
+		}
362
+	}
363
+
304 364
 	return 0;
305 365
 }
306 366
 
... ...
@@ -308,12 +368,19 @@ static int child_init(int rank)
308 368
 /*! \brief
309 369
  * Module destroy function
310 370
  */
311
-static void destroy(void)
312
-{
313
-	if(sub_dialog_table)
314
-	{
315
-	    pres_destroy_shtable(sub_dialog_table, sub_dialog_hash_size);
316
-	}	
371
+static void destroy(void) {
372
+	if (sub_dialog_table) {
373
+		pres_destroy_shtable(sub_dialog_table, sub_dialog_hash_size);
374
+	}
375
+
376
+	if (ul_dbh) {
377
+		ul_unlock_locks();
378
+		if (synchronize_all_udomains() != 0) {
379
+			LM_ERR("flushing cache failed\n");
380
+		}
381
+		ul_dbf.close(ul_dbh);
382
+	}
383
+
317 384
 	free_all_udomains();
318 385
 	ul_destroy_locks();
319 386
 
... ...
@@ -179,12 +179,10 @@ static void ul_rpc_dump(rpc_t* rpc, void* ctx)
179 179
 {
180 180
 	dlist_t* dl;
181 181
 	udomain_t* dom;
182
-	time_t t;
183 182
 	void* th;
184 183
 	void* sh;
185 184
 	int max, n, i;
186 185
 
187
-	t = time(0);
188 186
 	for( dl=root ; dl ; dl=dl->next ) {
189 187
 		dom = dl->d;
190 188
 		if (rpc->add(ctx, "{", &th) < 0)
... ...
@@ -53,6 +53,14 @@
53 53
 #include "../../modules/tm/dlg.h"
54 54
 #include "../cdp/diameter_ims_code_avp.h"
55 55
 
56
+#define DEFAULT_DBG_FILE "/var/log/usrloc_debug"
57
+
58
+/* DB modes */
59
+#define NO_DB         0
60
+#define WRITE_THROUGH 1
61
+#define WRITE_BACK    2		//not implemented yet
62
+#define DB_ONLY	      3		//not implemented yet
63
+
56 64
 /*IMPU states*/
57 65
 #define IMS_USER_NOT_REGISTERED 0		/** User not registered */
58 66
 #define IMS_USER_REGISTERED 1			/** User registered */
59 67
new file mode 100644
... ...
@@ -0,0 +1,725 @@
1
+#include "../../lib/srdb1/db.h"
2
+#include "usrloc.h"
3
+#include "usrloc_db.h"
4
+#include "bin_utils.h"
5
+#include "udomain.h"
6
+#include "math.h"
7
+
8
+str id_col = str_init(ID_COL); /*!< Name of column containing ID (gen. auto_increment field */
9
+str impu_id_col = str_init(IMPU_ID_COL); /*!< Name of column containing impu ID in mapping table */
10
+str contact_id_col = str_init(CONTACT_ID_COL); /*!< Name of column containing contact ID in mapping table */
11
+str impu_col = str_init(IMPU_COL); /*!< Name of column containing impu in impu table */
12
+str reg_state_col = str_init(REGSTATE_COL); /*!< Name of column containing reg state for aor */
13
+str barring_col = str_init(BARRING_COL); /*!< Name of column containing aor barring */
14
+str ccf1_col = str_init(CCF1_COL); /*!< Name of column containing ccf1 */
15
+str ccf2_col = str_init(CCF2_COL); /*!< Name of column containing ccf2 */
16
+str ecf1_col = str_init(ECF1_COL); /*!< Name of column containing ecf1 */
17
+str ecf2_col = str_init(ECF2_COL); /*!< Name of column containing ecf2 */
18
+str ims_sub_data_col = str_init(IMS_SUB_COL); /*!< Name of column containing ims_subscription data */
19
+str contact_col = str_init(CONTACT_COL); /*!< Name of column containing contact addresses */
20
+str expires_col = str_init(EXPIRES_COL); /*!< Name of column containing expires values */
21
+str q_col = str_init(Q_COL); /*!< Name of column containing q values */
22
+str callid_col = str_init(CALLID_COL); /*!< Name of column containing callid string */
23
+str cseq_col = str_init(CSEQ_COL); /*!< Name of column containing cseq values */
24
+str flags_col = str_init(FLAGS_COL); /*!< Name of column containing internal flags */
25
+str cflags_col = str_init(CFLAGS_COL); /*!< Name of column containing contact flags */
26
+str user_agent_col = str_init(USER_AGENT_COL); /*!< Name of column containing user agent string */
27
+str received_col = str_init(RECEIVED_COL); /*!< Name of column containing transport info of REGISTER */
28
+str path_col = str_init(PATH_COL); /*!< Name of column containing the Path header */
29
+str sock_col = str_init(SOCK_COL); /*!< Name of column containing the received socket */
30
+str methods_col = str_init(METHODS_COL); /*!< Name of column containing the supported methods */
31
+str last_mod_col = str_init(LAST_MOD_COL); /*!< Name of column containing the last modified date */
32
+
33
+str id_column 			= { "id", 2 };
34
+str impu_table 			= { "impu", 4 };
35
+str contact_table 		= { "contact", 7 };
36
+str impu_contact_table 	= { "impu_contact", 12 };
37
+str query_buffer 		= { 0, 0 };
38
+int query_buffer_len 	= 0;
39
+
40
+extern db1_con_t* ul_dbh;
41
+extern db_func_t ul_dbf;
42
+extern int ul_fetch_rows;
43
+
44
+int init_db(const str *db_url, int db_update_period, int fetch_num_rows) {
45
+	/* Find a database module */
46
+	if (db_bind_mod(db_url, &ul_dbf) < 0) {
47
+		LM_ERR("Unable to bind to a database driver\n");
48
+		return -1;
49
+	}
50
+
51
+	if (connect_db(db_url) != 0) {
52
+		LM_ERR("unable to connect to the database\n");
53
+		return -1;
54
+	}
55
+
56
+	if (!DB_CAPABILITY(ul_dbf, DB_CAP_ALL)) {
57
+		LM_ERR("database module does not implement all functions needed by the module\n");
58
+		return -1;
59
+	}
60
+
61
+	ul_dbf.close(ul_dbh);
62
+	ul_dbh = 0;
63
+
64
+	return 0;
65
+}
66
+
67
+int connect_db(const str *db_url) {
68
+	if (ul_dbh) { /* we've obviously already connected... */
69
+		LM_WARN("DB connection already open... continuing\n");
70
+		return 0;
71
+	}
72
+
73
+	if ((ul_dbh = ul_dbf.init(db_url)) == 0)
74
+		return -1;
75
+
76
+	LM_DBG("Successfully connected to DB and returned DB handle ptr %p\n", ul_dbh);
77
+	return 0;
78
+}
79
+
80
+void destroy_db() {
81
+	/* close the DB connection */
82
+	if (ul_dbh) {
83
+		ul_dbf.close(ul_dbh);
84
+		ul_dbh = 0;
85
+	}
86
+}
87
+
88
+int use_location_scscf_table(str* domain) {
89
+	if (!ul_dbh) {
90
+		LM_ERR("invalid database handle\n");
91
+		return -1;
92
+	}
93
+
94
+	if (ul_dbf.use_table(ul_dbh, domain) < 0) {
95
+		LM_ERR("Error in use_table\n");
96
+		return -1;
97
+	}
98
+
99
+	return 0;
100
+}
101
+
102
+int db_insert_impurecord(struct udomain* _d, str* public_identity,
103
+		int reg_state, int barring, ims_subscription** s, str* ccf1, str* ccf2,
104
+		str* ecf1, str* ecf2, struct impurecord** _r) {
105
+	int i;
106
+	bin_data x;
107
+	db_key_t key[8];
108
+	db_val_t val[8];
109
+	str bin_str;
110
+
111
+	//serialise ims_subscription
112
+	if (!bin_alloc(&x, 256)) {
113
+		LM_DBG("unable to allocate buffer for binary serialisation\n");
114
+		return -1;
115
+	}
116
+	if (!bin_encode_ims_subscription(&x, (*s))) {
117
+		LM_DBG("Unable to serialise ims_subscription data\n");
118
+		bin_free(&x);
119
+		return -1;
120
+	}
121
+	bin_str.s = x.s;
122
+	bin_str.len = x.len;
123
+
124
+	key[0] = &impu_col;
125
+	key[1] = &barring_col;
126
+	key[2] = &reg_state_col;
127
+
128
+	val[0].type = DB1_STR;
129
+	val[0].nul = 0;
130
+	val[0].val.str_val = *public_identity;
131
+	val[1].type = DB1_INT;
132
+	val[1].nul = 0;
133
+	val[1].val.int_val = barring;
134
+	val[2].type = DB1_INT;
135
+	val[2].nul = 0;
136
+	val[2].val.int_val = reg_state;
137
+
138
+	i = 3;
139
+
140
+	if (ccf1 && ccf1->s && ccf1->len >= 0) {
141
+		key[i] = &ccf1_col;
142
+		val[i].type = DB1_STR;
143
+		val[i].nul = 0;
144
+		val[i].val.str_val = *ccf1;
145
+		i++;
146
+	}
147
+	if (ecf1 && ecf1->s && ecf1->len >= 0) {
148
+		key[i] = &ecf1_col;
149
+		val[i].type = DB1_STR;
150
+		val[i].nul = 0;
151
+		val[i].val.str_val = *ecf1;
152
+		i++;
153
+	}
154
+	if (ccf2 && ccf2->s && ccf2->len >= 0) {
155
+		key[i] = &ccf2_col;
156
+		val[i].type = DB1_STR;
157
+		val[i].nul = 0;
158
+		val[i].val.str_val = *ccf2;
159
+		i++;
160
+	}
161
+	if (ecf2 && ecf2->s && ecf2->len >= 0) {
162
+		key[i] = &ecf2_col;
163
+		val[i].type = DB1_STR;
164
+		val[i].nul = 0;
165
+		val[i].val.str_val = *ecf2;
166
+		i++;
167
+	}
168
+	key[i] = &ims_sub_data_col;
169
+	val[i].type = DB1_BLOB;
170
+	val[i].nul = 0;
171
+	val[i].val.blob_val = bin_str;
172
+	i++;
173
+
174
+	if (ul_dbf.use_table(ul_dbh, &impu_table) != 0) {
175
+		LM_ERR("Unable to use table [%.*s]\n", impu_table.len, impu_table.s);
176
+		bin_free(&x);
177
+		return -1;
178
+	}
179
+	if (ul_dbf.insert_update(ul_dbh, key, val, i) != 0) {
180
+		LM_ERR("Unable to insert impu into table [%.*s]\n", public_identity->len, public_identity->s);
181
+		bin_free(&x);
182
+		return -1;
183
+	}
184
+	bin_free(&x);
185
+
186
+	return 0;
187
+}
188
+
189
+int db_delete_impurecord(udomain_t* _d, struct impurecord* _r) {
190
+	db_key_t key[1];
191
+	db_val_t val[1];
192
+
193
+	key[0] = &impu_col;
194
+	val[0].type = DB1_STR;
195
+	val[0].nul = 0;
196
+	val[0].val.str_val = _r->public_identity;
197
+
198
+	ul_dbf.use_table(ul_dbh, &impu_table);
199
+	ul_dbf.delete(ul_dbh, key, 0, val, 1);
200
+
201
+	return 0;
202
+}
203
+
204
+int db_insert_ucontact(impurecord_t* _r, ucontact_t* _c) {
205
+	db1_res_t* _rs;
206
+	int contact_id;
207
+	int impu_id;
208
+	db_key_t key[6];
209
+	db_val_t val[6];
210
+	db_key_t key_return[1];
211
+	db_val_t* ret_val;
212
+
213
+	key_return[0] = &id_column;
214
+
215
+	key[0] = &contact_col;
216
+	key[1] = &path_col;
217
+	key[2] = &user_agent_col;
218
+	key[3] = &received_col;
219
+	key[4] = &expires_col;
220
+	key[5] = &callid_col;
221
+
222
+	val[0].type = DB1_STR;
223
+	val[0].nul = 0;
224
+	val[0].val.str_val = _c->c;
225
+
226
+	val[1].type = DB1_STR;
227
+	val[1].nul = 0;
228
+	val[1].val.str_val = _c->path;
229
+
230
+	val[2].type = DB1_STR;
231
+	val[2].nul = 0;
232
+	val[2].val.str_val = _c->user_agent;
233
+
234
+	val[3].type = DB1_STR;
235
+	val[3].nul = 0;
236
+	val[3].val.str_val = _c->received;
237
+
238
+	val[4].type = DB1_DATETIME;
239
+	val[4].nul = 0;
240
+	val[4].val.time_val = _c->expires;
241
+
242
+	val[5].type = DB1_STR;
243
+	val[5].nul = 0;
244
+	val[5].val.str_val = _c->callid;
245
+
246
+	if (ul_dbf.use_table(ul_dbh, &contact_table) != 0) {
247
+		LM_ERR("Unable to use table [%.*s]\n", contact_table.len, contact_table.s);
248
+		return -1;
249
+	}
250
+	if (ul_dbf.insert_update(ul_dbh, key, val, 6) != 0) {
251
+		LM_ERR("Failed to insert/update contact record for [%.*s]\n", _c->c.len, _c->c.s);
252
+		return -1;
253
+	}
254
+	/* search for the ID if the contact just entered */
255
+	if (ul_dbf.query(ul_dbh, key, 0, val, key_return, 1, 1, NULL, &_rs) != 0) {
256
+		LM_ERR("Unable to find contact [%.*s] in DB to complete IMPU-contact mapping\n", _c->c.len, _c->c.s);
257
+		ul_dbf.free_result(ul_dbh, _rs);
258
+		return -1;
259
+	}
260
+
261
+	if (RES_ROW_N(_rs) == 0) {
262
+		LM_DBG("Contact %.*s not found in DB\n",_c->c.len, _c->c.s);
263
+		ul_dbf.free_result(ul_dbh, _rs);
264
+		return -1;
265
+	}
266
+
267
+	if (RES_ROW_N(_rs) > 1) {
268
+		LM_WARN("more than one contact found in DB for contact [%.*s] - this should not happen... proceeding with first entry\n",
269
+				_c->c.len, _c->c.s);
270
+	}
271
+
272
+	ret_val = ROW_VALUES(RES_ROWS(_rs));
273
+	contact_id = ret_val[0].val.int_val;
274
+	ul_dbf.free_result(ul_dbh, _rs);
275
+	LM_DBG("contact ID is %d\n", contact_id);
276
+
277
+	/* search for ID of the associated IMPU */
278
+	key[0] = &impu_col;
279
+	val[0].nul = 0;
280
+	val[0].type = DB1_STR;
281
+	val[0].val.str_val = _r->public_identity;
282
+
283
+	if (ul_dbf.use_table(ul_dbh, &impu_table) != 0) {
284
+		LM_ERR("Unable to use table [%.*s]\n", impu_table.len, impu_table.s);
285
+		return -1;
286
+	}
287
+	if (ul_dbf.query(ul_dbh, key, 0, val, key_return, 1, 1, NULL, &_rs) != 0) {
288
+		LM_ERR("Unable to find IMPU [%.*s] in DB to complete IMPU-contact mapping\n", _r->public_identity.len, _r->public_identity.s);
289
+		return -1;
290
+	}
291
+	if (RES_ROW_N(_rs) == 0) {
292
+		LM_DBG("IMPU %.*s not found in DB\n", _r->public_identity.len, _r->public_identity.s);
293
+		ul_dbf.free_result(ul_dbh, _rs);
294
+		return -1;
295
+	}
296
+
297
+	if (RES_ROW_N(_rs) > 1) {
298
+		LM_WARN("more than one IMPU found in DB for contact [%.*s] - this should not happen... proceeding with first entry\n",
299
+				_r->public_identity.len, _r->public_identity.s);
300
+	}
301
+	ret_val = ROW_VALUES(RES_ROWS(_rs));
302
+	impu_id = ret_val[0].val.int_val;
303
+
304
+	ul_dbf.free_result(ul_dbh, _rs);
305
+	LM_DBG("IMPU ID is %d\n", impu_id);
306
+
307
+	/* update mapping table between contact and IMPU */
308
+	key[0] = &impu_id_col;
309
+	key[1] = &contact_id_col;
310
+	val[0].nul = 0;
311
+	val[0].type = DB1_INT;
312
+	val[0].val.int_val = impu_id;
313
+	val[1].nul = 0;
314
+	val[1].type = DB1_INT;
315
+	val[1].val.int_val = contact_id;
316
+
317
+	if (ul_dbf.use_table(ul_dbh, &impu_contact_table) != 0) {
318
+		LM_ERR("Unable to use table [%.*s]\n", impu_table.len, impu_table.s);
319
+		return -1;
320
+	}
321
+
322
+	if (ul_dbf.insert_update(ul_dbh, key, val, 2) != 0) {
323
+		LM_ERR("Failed to insert/update impu-contact mapping record for contact [%.*s] and impu [%.*s]\n",
324
+				_c->c.len, _c->c.s,
325
+				_r->public_identity.len, _r->public_identity.s);
326
+		return -1;
327
+	}
328
+
329
+	return 0;
330
+}
331
+
332
+int db_delete_ucontact(impurecord_t* _r, ucontact_t* _c) {
333
+	db_key_t key[2];
334
+	db_val_t val[2];
335
+	db_key_t key_return[1];
336
+	db_val_t* ret_val;
337
+	db1_res_t* _rs;
338
+	int impu_id, contact_id;
339
+
340
+	LM_DBG("Deleting contact binding [%.*s] on impu [%.*s]\n",
341
+			_c->c.len, _c->c.s,
342
+			_r->public_identity.len, _r->public_identity.s);
343
+
344
+	/* get id of IMPU entry */
345
+	key[0] = &impu_col;
346
+	val[0].type = DB1_STR;
347
+	val[0].nul = 0;
348
+	val[0].val.str_val = _r->public_identity;
349
+	key_return[0] = &id_column;
350
+
351
+	if (ul_dbf.use_table(ul_dbh, &impu_table) != 0) {
352
+		LM_ERR("Unable to use table [%.*s]\n", impu_table.len, impu_table.s);
353
+		return -1;
354
+	}
355
+	if (ul_dbf.query(ul_dbh, key, 0, val, key_return, 1, 1, NULL, &_rs) != 0) {
356
+		LM_ERR("Unable to find IMPU [%.*s] in DB to complete IMPU-contact mapping\n", _r->public_identity.len, _r->public_identity.s);
357
+		return -1;
358
+	}
359
+	if (RES_ROW_N(_rs) == 0) {
360
+		LM_DBG("IMPU %.*s not found in DB\n", _r->public_identity.len, _r->public_identity.s);
361
+		ul_dbf.free_result(ul_dbh, _rs);
362
+		return -1;
363
+	}
364
+	if (RES_ROW_N(_rs) > 1) {
365
+		LM_WARN("more than one IMPU found in DB for contact [%.*s] - this should not happen... proceeding with first entry\n",
366
+				_r->public_identity.len, _r->public_identity.s);
367
+	}
368
+	ret_val = ROW_VALUES(RES_ROWS(_rs));
369
+	impu_id = ret_val[0].val.int_val;
370
+
371
+	ul_dbf.free_result(ul_dbh, _rs);
372
+	LM_DBG("IMPU ID is %d\n", impu_id);
373
+
374
+	/* get contact id from DB */
375
+	if (ul_dbf.use_table(ul_dbh, &contact_table) != 0) {
376
+		LM_ERR("Unable to use table [%.*s]\n", contact_table.len, contact_table.s);
377
+		return -1;
378
+	}
379
+	key[0] = &contact_col;
380
+	val[0].type = DB1_STR;
381
+	val[0].nul = 0;
382
+	val[0].val.str_val = _c->c;
383
+	if (ul_dbf.query(ul_dbh, key, 0, val, key_return, 1, 1, NULL, &_rs) != 0) {
384
+		LM_ERR("Unable to find contact [%.*s] in DB to complete IMPU-contact mapping removal\n", _c->c.len, _c->c.s);
385
+		return -1;
386
+	}
387
+	if (RES_ROW_N(_rs) == 0) {
388
+		LM_DBG("Contact %.*s not found in DB\n",_c->c.len, _c->c.s);
389
+		ul_dbf.free_result(ul_dbh, _rs);
390
+		return -1;
391
+	}
392
+	if (RES_ROW_N(_rs) > 1) {
393
+		LM_WARN("more than one contact found in DB for contact [%.*s] - this should not happen... proceeding with first entry\n",
394
+				_c->c.len, _c->c.s);
395
+	}
396
+	ret_val = ROW_VALUES(RES_ROWS(_rs));
397
+	contact_id = ret_val[0].val.int_val;
398
+	ul_dbf.free_result(ul_dbh, _rs);
399
+	LM_DBG("contact ID is %d\n", contact_id);
400
+
401
+	LM_DBG("need to remove contact-impu mapping %d:%d\n", impu_id, contact_id);
402
+
403
+	/* update impu-contact mapping table */
404
+	if (ul_dbf.use_table(ul_dbh, &impu_contact_table) != 0) {
405
+		LM_ERR("Unable to use table [%.*s]\n", impu_contact_table.len, impu_contact_table.s);
406
+		return -1;
407
+	}
408
+	key[0] = &contact_id_col;
409
+	key[1] = &impu_id_col;
410
+	val[0].type = DB1_INT;
411
+	val[0].nul = 0;
412
+	val[0].val.int_val = contact_id;
413
+	val[1].type = DB1_INT;
414
+	val[1].nul = 0;
415
+	val[1].val.int_val = impu_id;
416
+
417
+	if (ul_dbf.delete(ul_dbh, key, 0, val, 2) != 0) {
418
+		LM_ERR("unable to remove impu-contact mapping from DB for contact [%.*s], impu [%.*s]  ..... continuing\n",
419
+				_c->c.len, _c->c.s,
420
+				_r->public_identity.len, _r->public_identity.s);
421
+	}
422
+
423
+	/* delete contact from contact table - IFF there are no more mappings for it to impus */
424
+	if (ul_dbf.query(ul_dbh, key, 0, val, key_return, 1, 1, NULL, &_rs) != 0) {
425
+		LM_WARN("error searching for impu-contact mappings in DB\n");
426
+	}
427
+	if (RES_ROW_N(_rs) > 0) {
428
+		ul_dbf.free_result(ul_dbh, _rs);
429
+		LM_DBG("impu-contact mappings still exist, not removing contact from DB\n");
430
+		return 0;
431
+	}
432
+	ul_dbf.free_result(ul_dbh, _rs);
433
+
434
+	key[0] = &contact_col;
435
+	val[0].type = DB1_STR;
436
+	val[0].nul = 0;
437
+	val[0].val.str_val = _c->c;
438
+
439
+	if (ul_dbf.use_table(ul_dbh, &contact_table) != 0) {
440
+		LM_ERR("Unable to use table [%.*s]\n", contact_table.len, contact_table.s);
441
+		return -1;
442
+	}
443
+
444
+	if (ul_dbf.delete(ul_dbh, key, 0, val, 1) != 0) {
445
+		LM_ERR("unable to remove contact from DB [%.*s]\n", _c->c.len, _c->c.s);
446
+	}
447
+
448
+	return 0;
449
+}
450
+
451
+int inline int_to_str_len(int i) {
452
+	if (i < 0)
453
+		i = -i;
454
+	if (i < 10)
455
+		return 1;
456
+	if (i < 100)
457
+		return 2;
458
+	if (i < 1000)
459
+		return 3;
460
+	if (i < 10000)
461
+		return 4;
462
+	if (i < 100000)
463
+		return 5;
464
+	if (i < 1000000)
465
+		return 6;
466
+	if (i < 10000000)
467
+		return 7;
468
+	if (i < 100000000)
469
+		return 8;
470
+	if (i < 1000000000)
471
+		return 9;
472
+	return 10;
473
+}
474
+
475
+static inline int dbrow2contact(db_val_t* val, ucontact_info_t* ci) {
476
+	static str path, user_agent, callid;
477
+
478
+	/* path */
479
+	if (!VAL_NULL(val + 1)) {
480
+		path.s = (char*)VAL_STRING(val + 1);
481
+		path.len = strlen(path.s);
482
+	}
483
+	ci->path = &path;
484
+
485
+	/* user-agent */
486
+	if (!VAL_NULL(val + 2)) {
487
+		user_agent.s = (char*)VAL_STRING(val + 2);
488
+		user_agent.len = strlen(user_agent.s);
489
+	}
490
+	ci->user_agent = &user_agent;
491
+
492
+	/* received */
493
+	if (!VAL_NULL(val + 3)) {
494
+		ci->received.s = (char*)VAL_STRING(val + 3);
495
+		ci->received.len = strlen(ci->received.s);
496
+	}
497
+
498
+	/* expires */
499
+	if (!VAL_NULL(val + 4)) {
500
+		ci->expires = VAL_TIME(val + 4);
501
+	}
502
+	/* callid */
503
+	if (!VAL_NULL(val + 5)) {
504
+		callid.s = (char*) VAL_STRING(val + 5);
505
+		callid.len = strlen(callid.s);
506
+	}
507
+	ci->callid = &callid;
508
+
509
+	return 0;
510
+}
511
+
512
+int preload_udomain(db1_con_t* _c, udomain_t* _d) {
513
+	db_key_t col[9];
514
+	db_row_t* row;
515
+	db_row_t* contact_row;
516
+	db1_res_t* rs;
517
+	db1_res_t* contact_rs;
518
+	db_val_t* vals;
519
+	db_val_t* contact_vals;
520
+	int barring = 0, reg_state = 0, impu_id, n, nn, i, j, len;
521
+	str query, impu, ccf1 = { 0, 0 }, ecf1 = { 0, 0 }, ccf2 = { 0, 0 }, ecf2 = {
522
+			0, 0 }, blob = { 0, 0 }, contact={0,0};
523
+	bin_data x;
524
+	ims_subscription* subscription = 0;
525
+	impurecord_t* impurecord;
526
+	int impu_id_len;
527
+	ucontact_t* c;
528
+	ucontact_info_t contact_data;
529
+
530
+	/*
531
+	 * the two queries - get the IMPUs, then get associated contacts for each IMPU:
532
+	 * SELECT impu.impu,impu.barring,impu.reg_state,impu.ccf1,impu.ccf2,impu.ecf1,impu.ecf2,impu.ims_subscription_data FROM impu;
533
+	 * SELECT c.contact,c.path,c.user_agent,c.received,c.expires FROM impu_contact m LEFT JOIN contact c ON c.id=m.contact_id WHERE m.impu_id=20;
534
+	 */
535
+
536
+	char *p =
537
+			"SELECT c.contact,c.path,c.user_agent,c.received,c.expires,c.callid FROM impu_contact m LEFT JOIN contact c ON c.id=m.contact_id WHERE m.impu_id=";
538
+
539
+	query.s = p;
540
+	query.len = strlen(query.s);
541
+
542
+	col[0] = &impu_col;
543
+	col[1] = &barring_col;
544
+	col[2] = &reg_state_col;
545
+	col[3] = &ccf1_col;
546
+	col[4] = &ecf1_col;
547
+	col[5] = &ccf2_col;
548
+	col[6] = &ecf2_col;
549
+	col[7] = &ims_sub_data_col;
550
+	col[8] = &id_col;
551
+
552
+	if (ul_dbf.use_table(_c, &impu_table) != 0) {
553
+		LM_ERR("SQL use table failed\n");
554
+		return -1;
555
+	}
556
+	if (ul_dbf.query(_c, NULL, 0, NULL, col, 0, 9, NULL, &rs) != 0) {
557
+		LM_ERR("Unable to query DB to preload S-CSCF usrloc\n");
558
+		return -1;
559
+	}
560
+
561
+	if (RES_ROW_N(rs) == 0) {
562
+		LM_DBG("table is empty\n");
563
+		ul_dbf.free_result(_c, rs);
564
+		return 0;
565
+	}
566
+
567
+	LM_DBG("preloading S-CSCF usrloc...\n");
568
+	LM_DBG("%d rows returned in preload\n", RES_ROW_N(rs));
569
+
570
+	n = 0;
571
+	do {
572
+		LM_DBG("loading S-CSCF usrloc records - cycle [%d]\n", ++n);
573
+		for (i = 0; i < RES_ROW_N(rs); i++) {
574
+			impu_id = -1;
575
+
576
+			row = RES_ROWS(rs) + i;
577
+			LM_DBG("Fetching IMPU row %d\n", i+1);
578
+			vals = ROW_VALUES(row);
579
+
580
+			impu.s = (char*) VAL_STRING(vals);
581
+			if (VAL_NULL(vals) || !impu.s || !impu.s[0]) {
582
+				impu.len = 0;
583
+				impu.s = 0;
584
+			} else {
585
+				impu.len = strlen(impu.s);
586
+			}
587
+			LM_DBG("IMPU from DB is [%.*s]\n", impu.len, impu.s);
588
+			if (!VAL_NULL(vals + 1)) {
589
+				barring = VAL_INT(vals + 1);
590
+			}
591
+			if (!VAL_NULL(vals + 2)) {
592
+				reg_state = VAL_INT(vals + 2);
593
+			}
594
+			if (!VAL_NULL(vals + 3)) {
595
+				ccf1.s = (char*) VAL_STRING(vals + 3);
596
+				ccf1.len = strlen(ccf1.s);
597
+			}
598
+			LM_DBG("CCF1 from DB is [%.*s]\n", ccf1.len, ccf1.s);
599
+			if (!VAL_NULL(vals + 4)) {
600
+				ecf1.s = (char*) VAL_STRING(vals + 3);
601
+				ecf1.len = strlen(ecf1.s);
602
+			}
603
+			LM_DBG("ECF1 from DB is [%.*s]\n", ecf1.len, ecf1.s);
604
+			if (!VAL_NULL(vals + 5)) {
605
+				ccf2.s = (char*) VAL_STRING(vals + 5);
606
+				ccf2.len = strlen(ccf2.s);
607
+			}
608
+			LM_DBG("CCF2 from DB is [%.*s]\n", ccf2.len, ccf2.s);
609
+			if (!VAL_NULL(vals + 6)) {
610
+				ecf2.s = (char*) VAL_STRING(vals + 6);
611
+				ecf2.len = strlen(ecf2.s);
612
+			}
613
+			LM_DBG("ECF2 from DB is [%.*s]\n", ecf2.len, ecf2.s);
614
+
615
+			if (!VAL_NULL(vals + 7)) {
616
+				blob = VAL_BLOB(vals + 7);
617
+
618
+				bin_alloc(&x, VAL_BLOB(vals + 7).len);
619
+				memcpy(x.s, VAL_BLOB(vals + 7).s, VAL_BLOB(vals + 7).len);
620
+				x.s = blob.s;
621
+				x.len = blob.len;
622
+				x.max = 0;
623
+				subscription = bin_decode_ims_subscription(&x);
624
+				bin_free(&x);
625
+			}
626
+			if (!VAL_NULL(vals + 8)) {
627
+				impu_id = VAL_INT(vals + 8);
628
+			}
629
+
630
+			/* insert impu into memory */
631
+			lock_udomain(_d, &impu);
632
+			if (mem_insert_impurecord(_d, &impu, reg_state, barring,
633
+					&subscription, &ccf1, &ccf2, &ecf1, &ecf2, &impurecord)
634
+					!= 0) {
635
+				LM_ERR("Unable to insert IMPU into memory [%.*s]\n", impu.len, impu.s);
636
+			}
637
+
638
+			/* add contacts */
639
+			if (impu_id < 0) {
640
+				LM_ERR("impu_id has not been set [%.*s] - we cannot read contacts from DB....aborting preload\n", impu.len, impu.s);
641
+				//TODO: check frees
642
+				continue;
643
+			}
644
+			impu_id_len = int_to_str_len(impu_id);
645
+			len = query.len + impu_id_len + 1/*nul*/;
646
+			if (!query_buffer_len || query_buffer_len < len) {
647
+				if (query_buffer.s) {
648
+					pkg_free(query_buffer.s);
649
+				}
650
+				query_buffer.s = (char*) pkg_malloc(len);
651
+				if (!query_buffer.s) {
652
+					LM_ERR("mo more pkg mem\n");
653
+					//TODO: check free
654
+					return -1;
655
+				}
656
+				query_buffer_len = len;
657
+			}
658
+			memcpy(query_buffer.s, query.s, query.len);
659
+			p = query_buffer.s + query.len;
660
+			snprintf(p, impu_id_len + 1, "%d", impu_id);
661
+			query_buffer.len = query.len + impu_id_len;
662
+			if (ul_dbf.raw_query(_c, &query_buffer, &contact_rs) != 0) {
663
+				LM_ERR("Unable to query DB for contacts associated with impu [%.*s]\n",
664
+						impu.len, impu.s);
665
+				ul_dbf.free_result(_c, contact_rs);
666
+				continue;
667
+			}
668
+			if (RES_ROW_N(contact_rs) == 0) {
669
+				LM_DBG("no contacts associated with impu [%.*s]\n",impu.len, impu.s);
670
+				ul_dbf.free_result(_c, contact_rs);
671
+				continue;
672
+			}
673
+
674
+			nn = 0;
675
+			do {
676
+				LM_DBG("loading S-CSCF contact - cycle [%d]\n", ++nn);
677
+				for (j = 0; j < RES_ROW_N(contact_rs); j++) {
678
+					contact_row = RES_ROWS(contact_rs) + j;
679
+					contact_vals = ROW_VALUES(contact_row);
680
+
681
+					if (!VAL_NULL(contact_vals)) {
682
+						contact.s = (char*) VAL_STRING(contact_vals);
683
+						contact.len = strlen(contact.s);
684
+					}
685
+					if (dbrow2contact(contact_vals, &contact_data) != 0) {
686
+						LM_ERR("unable to convert contact row from DB into valid data... moving on\n");
687
+						continue;
688
+					}
689
+
690
+					if ((c = mem_insert_ucontact(impurecord, &contact, &contact_data)) == 0) {
691
+						LM_ERR("Unable to insert contact [%.*s] for IMPU [%.*s] into memory... continuing...\n",
692
+								contact.len, contact.s,
693
+								impu.len, impu.s);
694
+					}
695
+				}
696
+				if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
697
+					if (ul_dbf.fetch_result(_c, &contact_rs, ul_fetch_rows) < 0) {
698
+						LM_ERR("fetching rows failed\n");
699
+						ul_dbf.free_result(_c, contact_rs);
700
+						return -1;
701
+					}
702
+				} else {
703
+					break;
704
+				}
705
+			} while (RES_ROW_N(contact_rs) > 0);
706
+
707
+			unlock_udomain(_d, &impu);
708
+			ul_dbf.free_result(_c, contact_rs);
709
+		}
710
+
711
+		if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
712
+			if (ul_dbf.fetch_result(_c, &rs, ul_fetch_rows) < 0) {
713
+				LM_ERR("fetching rows (1) failed\n");
714
+				ul_dbf.free_result(_c, rs);
715
+				return -1;
716
+			}
717
+		} else {
718
+			break;
719
+		}
720
+	} while (RES_ROW_N(rs) > 0);
721
+
722
+	ul_dbf.free_result(_c, rs);
723
+
724
+	return 0;
725
+}
0 726
new file mode 100644
... ...
@@ -0,0 +1,48 @@
1
+#ifndef USRLOC_DB_H_
2
+#define USRLOC_DB_H_
3
+
4
+extern db1_con_t* ul_dbh;
5
+extern db_func_t ul_dbf;
6
+
7
+#define ID_COL 			"id"
8
+#define CONTACT_ID_COL "contact_id"
9
+#define IMPU_ID_COL    "impu_id"
10
+#define IMPU_COL       "impu"
11
+#define USER_COL       "username"
12
+#define DOMAIN_COL     "domain"
13
+#define CONTACT_COL    "contact"
14
+#define EXPIRES_COL    "expires"
15
+#define Q_COL          "q"
16
+#define CALLID_COL     "callid"
17
+#define CSEQ_COL       "cseq"
18
+#define FLAGS_COL      "flags"
19
+#define CFLAGS_COL     "cflags"
20
+#define USER_AGENT_COL "user_agent"
21
+#define RECEIVED_COL   "received"
22
+#define PATH_COL       "path"
23
+#define SOCK_COL       "socket"
24
+#define METHODS_COL    "methods"
25
+#define LAST_MOD_COL   "last_modified"
26
+#define REGSTATE_COL   "reg_state"
27
+#define BARRING_COL    "barring"
28
+#define CCF1_COL       "ccf1"
29
+#define CCF2_COL       "ccf2"
30
+#define ECF1_COL       "ecf1"
31
+#define ECF2_COL       "ecf2"
32
+#define IMS_SUB_COL    "ims_subscription_data"
33
+
34
+int init_db(const str *db_url, int db_update_period, int fetch_num_rows);
35
+int connect_db(const str *db_url);
36
+void destroy_db();
37
+int use_location_pcscf_table(str* domain);
38
+
39
+int db_insert_impurecord(struct udomain* _d, str* public_identity, int reg_state, int barring,
40
+		ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2,
41
+		struct impurecord** _r);
42
+int db_delete_impurecord(udomain_t* _d, struct impurecord* _r);
43
+int db_insert_ucontact(impurecord_t* _r, ucontact_t* _c);
44
+int db_delete_ucontact(impurecord_t* _r, ucontact_t* _c);
45
+
46
+int preload_udomain(db1_con_t* _c, udomain_t* _d);
47
+
48
+#endif /* USRLOC_DB_H_ */