Browse code

Revert "sanity: fix sanity_reply function name for config exports"

This reverts commit eeefe7dcc2af90e7def8f1698e8f79d0dd020043.

Daniel-Constantin Mierla authored on 04/05/2022 14:33:08
Showing 1 changed files
... ...
@@ -1,7 +1,7 @@
1 1
 /*
2 2
  * Copyright (C) 2001-2003 FhG Fokus
3 3
  * Copyright (C) 2007-2008 1&1 Internet AG
4
- *
4
+ * 
5 5
  * This file is part of Kamailio, a free SIP server.
6 6
  *
7 7
  * Kamailio is free software; you can redistribute it and/or modify
... ...
@@ -14,8 +14,8 @@
14 14
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 15
  * GNU General Public License for more details.
16 16
  *
17
- * You should have received a copy of the GNU General Public License
18
- * along with this program; if not, write to the Free Software
17
+ * You should have received a copy of the GNU General Public License 
18
+ * along with this program; if not, write to the Free Software 
19 19
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20 20
  */
21 21
 
... ...
@@ -294,7 +294,7 @@ db1_con_t* db_do_init2(const str* url, void* (*new_connection)(), db_pooling_t p
294 294
 		LM_ERR("The configured db_url is too long\n");
295 295
 		return 0;
296 296
 	}
297
-
297
+	
298 298
 	/* this is the root memory for this database connection. */
299 299
 	res = (db1_con_t*)pkg_malloc(con_size);
300 300
 	if (!res) {
Browse code

sanity: fix sanity_reply function name for config exports

Daniel-Constantin Mierla authored on 04/05/2022 14:25:03
Showing 1 changed files
... ...
@@ -1,7 +1,7 @@
1 1
 /*
2 2
  * Copyright (C) 2001-2003 FhG Fokus
3 3
  * Copyright (C) 2007-2008 1&1 Internet AG
4
- * 
4
+ *
5 5
  * This file is part of Kamailio, a free SIP server.
6 6
  *
7 7
  * Kamailio is free software; you can redistribute it and/or modify
... ...
@@ -14,8 +14,8 @@
14 14
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 15
  * GNU General Public License for more details.
16 16
  *
17
- * You should have received a copy of the GNU General Public License 
18
- * along with this program; if not, write to the Free Software 
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19 19
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20 20
  */
21 21
 
... ...
@@ -294,7 +294,7 @@ db1_con_t* db_do_init2(const str* url, void* (*new_connection)(), db_pooling_t p
294 294
 		LM_ERR("The configured db_url is too long\n");
295 295
 		return 0;
296 296
 	}
297
-	
297
+
298 298
 	/* this is the root memory for this database connection. */
299 299
 	res = (db1_con_t*)pkg_malloc(con_size);
300 300
 	if (!res) {
Browse code

lib/srdb1: db_use_table() more suggestive error messages

Daniel-Constantin Mierla authored on 17/09/2020 10:55:10
Showing 1 changed files
... ...
@@ -477,8 +477,12 @@ int db_check_table_version(db_func_t* dbf, db1_con_t* dbh, const str* table,
477 477
  */
478 478
 int db_use_table(db1_con_t* _h, const str* _t)
479 479
 {
480
-	if (!_h || !_t || !_t->s) {
481
-		LM_ERR("invalid parameter value\n");
480
+	if (!_h) {
481
+		LM_ERR("invalid connection parameter\n");
482
+		return -1;
483
+	}
484
+	if (!_t || !_t->s) {
485
+		LM_ERR("invalid table parameter value\n");
482 486
 		return -1;
483 487
 	}
484 488
 
Browse code

lib: add missing line-break in DB init function error log

Henning Westerholt authored on 30/06/2019 15:49:25
Showing 1 changed files
... ...
@@ -316,7 +316,7 @@ db1_con_t* db_do_init2(const str* url, void* (*new_connection)(), db_pooling_t p
316 316
 		/* Not in the pool yet */
317 317
 		con = new_connection(id);
318 318
 		if (!con) {
319
-			LM_ERR("could not add connection to the pool");
319
+			LM_ERR("could not add connection to the pool\n");
320 320
 			goto err;
321 321
 		}
322 322
 		pool_insert((struct pool_con*)con);
Browse code

lib: extend (doxygen) comments for db_table_version and db_check_table_version

Henning Westerholt authored on 01/01/2019 21:12:06
Showing 1 changed files
... ...
@@ -358,13 +358,16 @@ void db_do_close(db1_con_t* _h, void (*free_connection)())
358 358
 }
359 359
 
360 360
 
361
-
362
-/*! \brief
363
- * Get version of a table
364
- * \param dbf
365
- * \param connection
366
- * \param table
367
- * \return If there is no row for the given table, return version 0
361
+/**
362
+ * \brief Get the version of a table.
363
+ *
364
+ * Returns the version number of a given table from the version table.
365
+ * Instead of this function you should use db_check_table_version!
366
+ * \see db_check_table_version
367
+ * \param dbf database module callbacks
368
+ * \param con database connection handle
369
+ * \param table checked table
370
+ * \return the version number if present, 0 if no version data available, < 0 on error
368 371
  */
369 372
 int db_table_version(const db_func_t* dbf, db1_con_t* connection, const str* table)
370 373
 {
... ...
@@ -442,9 +445,15 @@ int db_table_version(const db_func_t* dbf, db1_con_t* connection, const str* tab
442 445
 	return ret;
443 446
 }
444 447
 
445
-/*! \brief
446
- * Check the table version
447
- * 0 means ok, -1 means an error occurred
448
+/**
449
+ * \brief Check the table version, including user error logging.
450
+ *
451
+ * Small helper function to check the table version, including user error logging.
452
+ * \param dbf database module callbacks
453
+ * \param dbh database connection handle
454
+ * \param table checked table
455
+ * \param version checked version
456
+ * \return 0 means ok, -1 means an error occurred
448 457
  */
449 458
 int db_check_table_version(db_func_t* dbf, db1_con_t* dbh, const str* table,
450 459
 		const unsigned int version)
Browse code

lib: refactor srdb1 DB1 API to use common pkg memory helper logging #define

Henning Westerholt authored on 26/12/2018 13:25:09
Showing 1 changed files
... ...
@@ -177,7 +177,7 @@ int db_bind_mod(const str* mod, db_func_t* mydbf)
177 177
 	// add the prefix
178 178
 	name = pkg_malloc(mod->len + 4);
179 179
 	if (!name) {
180
-		LM_ERR("no private memory left\n");
180
+		PKG_MEM_ERROR;
181 181
 		return -1;
182 182
 	}
183 183
 	memcpy(name, "db_", 3);
... ...
@@ -189,7 +189,7 @@ int db_bind_mod(const str* mod, db_func_t* mydbf)
189 189
 		len = p - name;
190 190
 		tmp = (char*)pkg_malloc(len + 4);
191 191
 		if (!tmp) {
192
-			LM_ERR("no private memory left\n");
192
+			PKG_MEM_ERROR;
193 193
 			pkg_free(name);
194 194
 			return -1;
195 195
 		}
... ...
@@ -298,7 +298,7 @@ db1_con_t* db_do_init2(const str* url, void* (*new_connection)(), db_pooling_t p
298 298
 	/* this is the root memory for this database connection. */
299 299
 	res = (db1_con_t*)pkg_malloc(con_size);
300 300
 	if (!res) {
301
-		LM_ERR("no private memory left\n");
301
+		PKG_MEM_ERROR;
302 302
 		return 0;
303 303
 	}
304 304
 	memset(res, 0, con_size);
Browse code

lib/srdb1: memset db connection structure earlier in db_bind_mod()

Daniel-Constantin Mierla authored on 30/11/2018 08:19:16
Showing 1 changed files
... ...
@@ -163,6 +163,12 @@ int db_bind_mod(const str* mod, db_func_t* mydbf)
163 163
 		LM_CRIT("null dbf parameter\n");
164 164
 		return -1;
165 165
 	}
166
+
167
+	/* for safety we initialize mydbf with 0 (this will cause
168
+	 *  a segfault immediately if someone tries to call a function
169
+	 *  from it without checking the return code from bind_dbmod */
170
+	memset((void*)mydbf, 0, sizeof(db_func_t));
171
+
166 172
 	if (mod->len > MAX_URL_LENGTH)
167 173
 	{
168 174
 		LM_ERR("SQL URL too long\n");
... ...
@@ -178,11 +184,6 @@ int db_bind_mod(const str* mod, db_func_t* mydbf)
178 184
 	memcpy(name+3, mod->s, mod->len);
179 185
 	name[mod->len+3] = 0;
180 186
 
181
-	/* for safety we initialize mydbf with 0 (this will cause
182
-	 *  a segfault immediately if someone tries to call a function
183
-	 *  from it without checking the return code from bind_dbmod */
184
-	memset((void*)mydbf, 0, sizeof(db_func_t));
185
-
186 187
 	p = strchr(name, ':');
187 188
 	if (p) {
188 189
 		len = p - name;
Browse code

lib/srdb1: cast types to get rid of compile warnings

Daniel-Constantin Mierla authored on 01/10/2018 06:31:29
Showing 1 changed files
... ...
@@ -445,14 +445,17 @@ int db_table_version(const db_func_t* dbf, db1_con_t* connection, const str* tab
445 445
  * Check the table version
446 446
  * 0 means ok, -1 means an error occurred
447 447
  */
448
-int db_check_table_version(db_func_t* dbf, db1_con_t* dbh, const str* table, const unsigned int version)
448
+int db_check_table_version(db_func_t* dbf, db1_con_t* dbh, const str* table,
449
+		const unsigned int version)
449 450
 {
450 451
 	int ver = db_table_version(dbf, dbh, table);
451 452
 	if (ver < 0) {
452 453
 		LM_ERR("querying version for table %.*s\n", table->len, table->s);
453 454
 		return -1;
454
-	} else if (ver != version) {
455
-		LM_ERR("invalid version %d for table %.*s found, expected %d (check table structure and table \"version\")\n", ver, table->len, table->s, version);
455
+	} else if (ver != (int)version) {
456
+		LM_ERR("invalid version %d for table %.*s found, expected %u"
457
+				" (check table structure and table \"version\")\n",
458
+				ver, table->len, table->s, version);
456 459
 		return -1;
457 460
 	}
458 461
 	return 0;
Browse code

lib/srdb1: handle DB1_UINT and DB1_UBIGINT for db version check

Daniel-Constantin Mierla authored on 01/10/2018 06:28:38
Showing 1 changed files
... ...
@@ -391,9 +391,9 @@ int db_table_version(const db_func_t* dbf, db1_con_t* connection, const str* tab
391 391
 	VAL_TYPE(val) = DB1_STR;
392 392
 	VAL_NULL(val) = 0;
393 393
 	VAL_STR(val) = *table;
394
-	
394
+
395 395
 	col[0] = &tmp2;
396
-	
396
+
397 397
 	if (dbf->query(connection, key, 0, val, col, 1, 1, 0, &res) < 0) {
398 398
 		LM_ERR("error in db_query\n");
399 399
 		return -1;
... ...
@@ -414,7 +414,8 @@ int db_table_version(const db_func_t* dbf, db1_con_t* connection, const str* tab
414 414
 
415 415
 	ver = ROW_VALUES(RES_ROWS(res));
416 416
 	val_type = VAL_TYPE(ver);
417
-	if ( (val_type!=DB1_INT && val_type!=DB1_DOUBLE && val_type!=DB1_BIGINT)
417
+	if ( (val_type!=DB1_INT && val_type!=DB1_DOUBLE && val_type!=DB1_BIGINT
418
+				&& val_type!=DB1_UINT && val_type!=DB1_UBIGINT)
418 419
 			|| VAL_NULL(ver) ) {
419 420
 		LM_ERR("invalid type (%d) or nul (%d) version "
420 421
 			"columns for %.*s\n", VAL_TYPE(ver), VAL_NULL(ver),
... ...
@@ -425,8 +426,12 @@ int db_table_version(const db_func_t* dbf, db1_con_t* connection, const str* tab
425 426
 
426 427
 	if (val_type == DB1_INT) {
427 428
 		ret = VAL_INT(ver);
429
+	} else if (val_type == DB1_UINT) {
430
+		ret = (int)VAL_UINT(ver);
428 431
 	} else if (val_type == DB1_BIGINT) {
429 432
 		ret = (int)VAL_BIGINT(ver);
433
+	} else if (val_type == DB1_UBIGINT) {
434
+		ret = (int)VAL_UBIGINT(ver);
430 435
 	} else if (val_type == DB1_DOUBLE) {
431 436
 		ret = (int)VAL_DOUBLE(ver);
432 437
 	}
Browse code

lib/srdb1: increased the safety check for max db url to 1023

- was 255, too small for large connection strings needed for no-sql
- reported by GH #1545

Daniel-Constantin Mierla authored on 28/05/2018 13:33:21
Showing 1 changed files
... ...
@@ -60,7 +60,7 @@
60 60
 #include "db_query.h"
61 61
 #include "db.h"
62 62
 
63
-static unsigned int MAX_URL_LENGTH = 255;	/*!< maximum length of a SQL URL */
63
+static unsigned int MAX_URL_LENGTH = 1023;	/*!< maximum length of a SQL URL */
64 64
 
65 65
 
66 66
 int db_check_api(db_func_t* dbf, char *mname)
Browse code

lib/srdb1: db_table_version() can handle DB1_BIGINT and DB1_DOUBLE values

- in case of views or other database engine, the type for version value
can be different that DB1_INT. If it is a number, cast it to int
- extracted from GH #1186 by Emmanuel Schmidbauer
<emmanuel@getweave.com>

Daniel-Constantin Mierla authored on 13/07/2017 07:03:54
Showing 1 changed files
... ...
@@ -374,7 +374,8 @@ int db_table_version(const db_func_t* dbf, db1_con_t* connection, const str* tab
374 374
 	str *version = &version_table;
375 375
 	str tmp1 = str_init(TABLENAME_COLUMN);
376 376
 	str tmp2 = str_init(VERSION_COLUMN);
377
-	int ret;
377
+	int ret = 0;
378
+	int val_type;
378 379
 
379 380
 	if (!dbf||!connection || !table || !table->s) {
380 381
 		LM_CRIT("invalid parameter value\n");
... ...
@@ -412,7 +413,9 @@ int db_table_version(const db_func_t* dbf, db1_con_t* connection, const str* tab
412 413
 	}
413 414
 
414 415
 	ver = ROW_VALUES(RES_ROWS(res));
415
-	if ( VAL_TYPE(ver)!=DB1_INT || VAL_NULL(ver) ) {
416
+	val_type = VAL_TYPE(ver);
417
+	if ( (val_type!=DB1_INT && val_type!=DB1_DOUBLE && val_type!=DB1_BIGINT)
418
+			|| VAL_NULL(ver) ) {
416 419
 		LM_ERR("invalid type (%d) or nul (%d) version "
417 420
 			"columns for %.*s\n", VAL_TYPE(ver), VAL_NULL(ver),
418 421
 			table->len, ZSW(table->s));
... ...
@@ -420,8 +423,16 @@ int db_table_version(const db_func_t* dbf, db1_con_t* connection, const str* tab
420 423
 		return -1;
421 424
 	}
422 425
 
423
-	ret = VAL_INT(ver);
426
+	if (val_type == DB1_INT) {
427
+		ret = VAL_INT(ver);
428
+	} else if (val_type == DB1_BIGINT) {
429
+		ret = (int)VAL_BIGINT(ver);
430
+	} else if (val_type == DB1_DOUBLE) {
431
+		ret = (int)VAL_DOUBLE(ver);
432
+	}
433
+
424 434
 	dbf->free_result(connection, res);
435
+
425 436
 	return ret;
426 437
 }
427 438
 
Browse code

core, lib, modules: updated include paths for header files

Daniel-Constantin Mierla authored on 07/12/2016 11:07:22
Showing 1 changed files
... ...
@@ -49,11 +49,11 @@
49 49
  * - \ref ../modules/db_unixodbc
50 50
  */
51 51
 
52
-#include "../../dprint.h"
53
-#include "../../sr_module.h"
54
-#include "../../mem/mem.h"
55
-#include "../../ut.h"
56
-#include "../../globals.h"
52
+#include "../../core/dprint.h"
53
+#include "../../core/sr_module.h"
54
+#include "../../core/mem/mem.h"
55
+#include "../../core/ut.h"
56
+#include "../../core/globals.h"
57 57
 #include "db_cap.h"
58 58
 #include "db_id.h"
59 59
 #include "db_pool.h"
Browse code

core, lib, modules: restructured source code tree

- new folder src/ to hold the source code for main project applications
- main.c is in src/
- all core files are subfolder are in src/core/
- modules are in src/modules/
- libs are in src/lib/
- application Makefiles are in src/
- application binary is built in src/ (src/kamailio)

Daniel-Constantin Mierla authored on 07/12/2016 11:03:51
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,524 @@
1
+/*
2
+ * Copyright (C) 2001-2003 FhG Fokus
3
+ * Copyright (C) 2007-2008 1&1 Internet AG
4
+ * 
5
+ * This file is part of Kamailio, a free SIP server.
6
+ *
7
+ * Kamailio is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * Kamailio is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License 
18
+ * along with this program; if not, write to the Free Software 
19
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20
+ */
21
+
22
+/**
23
+ * \file lib/srdb1/db.c
24
+ * \ingroup db1
25
+ * \brief Generic Database Interface
26
+ *
27
+ */
28
+/*! \defgroup db DB: The Kamailio generic database interface
29
+ * This is a generic database interface for modules that need to utilize a
30
+ * database. The interface should be used by all modules that access database.
31
+ * The interface will be independent of the underlying database server.
32
+ * Notes:
33
+ * If possible, use the predefined macros if you need to access any structure
34
+ * attributes.
35
+ * For additional description, see the comments in the sources of mysql module.
36
+ *
37
+ * If you want to see more complicated examples of how the API could be used,
38
+ * take a look at the sources of the usrloc or auth modules.
39
+ * - \ref usrloc
40
+ * - \ref auth
41
+ *
42
+ * Implemented modules
43
+ * - \ref ../modules/db_berkeley
44
+ * - \ref ../modules/db_flatstore
45
+ * - \ref ../modules/db_text
46
+ * - \ref ../modules/db_mysql
47
+ * - \ref ../modules/db_oracle
48
+ * - \ref ../modules/db_postgres
49
+ * - \ref ../modules/db_unixodbc
50
+ */
51
+
52
+#include "../../dprint.h"
53
+#include "../../sr_module.h"
54
+#include "../../mem/mem.h"
55
+#include "../../ut.h"
56
+#include "../../globals.h"
57
+#include "db_cap.h"
58
+#include "db_id.h"
59
+#include "db_pool.h"
60
+#include "db_query.h"
61
+#include "db.h"
62
+
63
+static unsigned int MAX_URL_LENGTH = 255;	/*!< maximum length of a SQL URL */
64
+
65
+
66
+int db_check_api(db_func_t* dbf, char *mname)
67
+{
68
+	if(dbf==NULL)
69
+		return -1;
70
+
71
+	/* All modules must export db_use_table */
72
+	if (dbf->use_table == 0) {
73
+		LM_ERR("module %s does not export db_use_table function. Please check if module is loaded.\n", mname);
74
+		goto error;
75
+	}
76
+
77
+	/* All modules must export db_init */
78
+	if (dbf->init == 0) {
79
+		LM_ERR("module %s does not export db_init function. Please check if module is loaded.\n", mname);
80
+		goto error;
81
+	}
82
+
83
+	/* All modules must export db_close */
84
+	if (dbf->close == 0) {
85
+		LM_ERR("module %s does not export db_close function. Please check if module is loaded.\n", mname);
86
+		goto error;
87
+	}
88
+
89
+	if (dbf->query) {
90
+		dbf->cap |= DB_CAP_QUERY;
91
+	}
92
+
93
+	if (dbf->fetch_result) {
94
+		dbf->cap |= DB_CAP_FETCH;
95
+	}
96
+
97
+	if (dbf->raw_query) {
98
+		dbf->cap |= DB_CAP_RAW_QUERY;
99
+	}
100
+
101
+	/* Free result must be exported if DB_CAP_QUERY or
102
+	 * DB_CAP_RAW_QUERY is set */
103
+	if ((dbf->cap & (DB_CAP_QUERY|DB_CAP_RAW_QUERY)) && (dbf->free_result==0)) {
104
+		LM_ERR("module %s supports queries but does not export free_result\n",
105
+				mname);
106
+		goto error;
107
+	}
108
+
109
+	if (dbf->insert) {
110
+		dbf->cap |= DB_CAP_INSERT;
111
+	}
112
+
113
+	if (dbf->delete) {
114
+		dbf->cap |= DB_CAP_DELETE;
115
+	}
116
+
117
+	if (dbf->update) {
118
+		dbf->cap |= DB_CAP_UPDATE;
119
+	}
120
+
121
+	if (dbf->replace) {
122
+		dbf->cap |= DB_CAP_REPLACE;
123
+	}
124
+
125
+	if (dbf->last_inserted_id) {
126
+		dbf->cap |= DB_CAP_LAST_INSERTED_ID;
127
+	}
128
+
129
+	if (dbf->insert_update) {
130
+		dbf->cap |= DB_CAP_INSERT_UPDATE;
131
+	}
132
+
133
+	if (dbf->insert_delayed) {
134
+		dbf->cap |= DB_CAP_INSERT_DELAYED;
135
+	}
136
+
137
+	if (dbf->affected_rows) {
138
+		dbf->cap |= DB_CAP_AFFECTED_ROWS;
139
+	}
140
+
141
+	return 0;
142
+error:
143
+	return -1;
144
+}
145
+
146
+/*! \brief fills mydbf with the corresponding db module callbacks
147
+ * \param mod
148
+ * \param mydbf
149
+ * \return returns 0 on success, -1 on error
150
+ * \note on error mydbf will contain only 0s */
151
+int db_bind_mod(const str* mod, db_func_t* mydbf)
152
+{
153
+	char *name, *tmp, *p;
154
+	int len;
155
+	db_func_t dbf;
156
+	db_bind_api_f dbind;
157
+
158
+	if (!mod || !mod->s) {
159
+		LM_CRIT("null database module name\n");
160
+		return -1;
161
+	}
162
+	if (mydbf==0) {
163
+		LM_CRIT("null dbf parameter\n");
164
+		return -1;
165
+	}
166
+	if (mod->len > MAX_URL_LENGTH)
167
+	{
168
+		LM_ERR("SQL URL too long\n");
169
+		return -1;
170
+	}
171
+	// add the prefix
172
+	name = pkg_malloc(mod->len + 4);
173
+	if (!name) {
174
+		LM_ERR("no private memory left\n");
175
+		return -1;
176
+	}
177
+	memcpy(name, "db_", 3);
178
+	memcpy(name+3, mod->s, mod->len);
179
+	name[mod->len+3] = 0;
180
+
181
+	/* for safety we initialize mydbf with 0 (this will cause
182
+	 *  a segfault immediately if someone tries to call a function
183
+	 *  from it without checking the return code from bind_dbmod */
184
+	memset((void*)mydbf, 0, sizeof(db_func_t));
185
+
186
+	p = strchr(name, ':');
187
+	if (p) {
188
+		len = p - name;
189
+		tmp = (char*)pkg_malloc(len + 4);
190
+		if (!tmp) {
191
+			LM_ERR("no private memory left\n");
192
+			pkg_free(name);
193
+			return -1;
194
+		}
195
+		memcpy(tmp, name, len);
196
+		tmp[len] = '\0';
197
+		pkg_free(name);
198
+	} else {
199
+		tmp = name;
200
+	}
201
+
202
+	if (!find_module_by_name(tmp)) {
203
+		LM_ERR("Module %s not found. Missing loadmodule? \n", tmp);
204
+		goto error;
205
+	}
206
+	dbind = (db_bind_api_f)find_mod_export(tmp, "db_bind_api", 0, 0);
207
+	if(dbind != NULL)
208
+	{
209
+		LM_DBG("using db bind api for %s\n", tmp);
210
+		if(dbind(&dbf)<0)
211
+		{
212
+			LM_ERR("db_bind_api returned error for module %s\n", tmp);
213
+			goto error;
214
+		}
215
+	} else {
216
+		memset(&dbf, 0, sizeof(db_func_t));
217
+		LM_DBG("using export interface to bind %s\n", tmp);
218
+		dbf.use_table = (db_use_table_f)find_mod_export(tmp,
219
+			"db_use_table", 2, 0);
220
+		dbf.init = (db_init_f)find_mod_export(tmp, "db_init", 1, 0);
221
+		dbf.init2 = (db_init2_f)find_mod_export(tmp, "db_init2", 1, 0);
222
+		dbf.close = (db_close_f)find_mod_export(tmp, "db_close", 2, 0);
223
+		dbf.query = (db_query_f)find_mod_export(tmp, "db_query", 2, 0);
224
+		dbf.fetch_result = (db_fetch_result_f)find_mod_export(tmp,
225
+			"db_fetch_result", 2, 0);
226
+		dbf.raw_query = (db_raw_query_f)find_mod_export(tmp,
227
+			"db_raw_query", 2, 0);
228
+		dbf.free_result = (db_free_result_f)find_mod_export(tmp,
229
+			"db_free_result", 2, 0);
230
+		dbf.insert = (db_insert_f)find_mod_export(tmp, "db_insert", 2, 0);
231
+		dbf.delete = (db_delete_f)find_mod_export(tmp, "db_delete", 2, 0);
232
+		dbf.update = (db_update_f)find_mod_export(tmp, "db_update", 2, 0);
233
+		dbf.replace = (db_replace_f)find_mod_export(tmp, "db_replace", 2, 0);
234
+		dbf.last_inserted_id= (db_last_inserted_id_f)find_mod_export(tmp,
235
+			"db_last_inserted_id", 1, 0);
236
+		dbf.affected_rows = (db_affected_rows_f)find_mod_export(tmp,
237
+			"db_affected_rows", 1, 0);
238
+		dbf.insert_update = (db_insert_update_f)find_mod_export(tmp,
239
+			"db_insert_update", 2, 0);
240
+		dbf.insert_delayed = (db_insert_delayed_f)find_mod_export(tmp,
241
+			"db_insert_delayed", 2, 0);
242
+		dbf.start_transaction = (db_start_transaction_f)find_mod_export(tmp,
243
+			"db_start_transaction", 2, 0);
244
+		dbf.end_transaction = (db_end_transaction_f)find_mod_export(tmp,
245
+			"db_end_transaction", 1, 0);
246
+		dbf.abort_transaction = (db_abort_transaction_f)find_mod_export(tmp,
247
+			"db_abort_transaction", 1, 0);
248
+		dbf.query_lock = (db_query_f)find_mod_export(tmp, "db_query_lock", 2, 0);
249
+	}
250
+	if(db_check_api(&dbf, tmp)!=0)
251
+		goto error;
252
+
253
+	*mydbf=dbf; /* copy */
254
+	pkg_free(tmp);
255
+	return 0;
256
+
257
+error:
258
+	pkg_free(tmp);
259
+	return -1;
260
+}
261
+
262
+
263
+/*! \brief
264
+ * Initialize database module
265
+ * \note No function should be called before this
266
+ */
267
+db1_con_t* db_do_init(const str* url, void* (*new_connection)())
268
+{
269
+	return db_do_init2(url, *new_connection, DB_POOLING_PERMITTED);
270
+}
271
+
272
+
273
+/*! \brief
274
+ * Initialize database module
275
+ * \note No function should be called before this
276
+ */
277
+db1_con_t* db_do_init2(const str* url, void* (*new_connection)(), db_pooling_t pooling)
278
+{
279
+	struct db_id* id;
280
+	void* con;
281
+	db1_con_t* res;
282
+
283
+	int con_size = sizeof(db1_con_t) + sizeof(void *);
284
+	id = 0;
285
+	res = 0;
286
+
287
+	if (!url || !url->s || !new_connection) {
288
+		LM_ERR("invalid parameter value\n");
289
+		return 0;
290
+	}
291
+	if (url->len > MAX_URL_LENGTH)
292
+	{
293
+		LM_ERR("The configured db_url is too long\n");
294
+		return 0;
295
+	}
296
+	
297
+	/* this is the root memory for this database connection. */
298
+	res = (db1_con_t*)pkg_malloc(con_size);
299
+	if (!res) {
300
+		LM_ERR("no private memory left\n");
301
+		return 0;
302
+	}
303
+	memset(res, 0, con_size);
304
+
305
+	id = new_db_id(url, pooling);
306
+	if (!id) {
307
+		LM_ERR("cannot parse URL '%.*s'\n", url->len, url->s);
308
+		goto err;
309
+	}
310
+
311
+	/* Find the connection in the pool */
312
+	con = pool_get(id);
313
+	if (!con) {
314
+		LM_DBG("connection %p not found in pool\n", id);
315
+		/* Not in the pool yet */
316
+		con = new_connection(id);
317
+		if (!con) {
318
+			LM_ERR("could not add connection to the pool");
319
+			goto err;
320
+		}
321
+		pool_insert((struct pool_con*)con);
322
+	} else {
323
+		LM_DBG("connection %p found in pool\n", id);
324
+		free_db_id(id); // free the new id, as we use the pool instead
325
+		id = 0;
326
+	}
327
+
328
+	res->tail = (unsigned long)con;
329
+	return res;
330
+
331
+ err:
332
+	if (id) free_db_id(id);
333
+	if (res) pkg_free(res);
334
+	return 0;
335
+}
336
+
337
+
338
+/*! \brief
339
+ * Shut down database module
340
+ * \note No function should be called after this
341
+ */
342
+void db_do_close(db1_con_t* _h, void (*free_connection)())
343
+{
344
+	struct pool_con* con;
345
+
346
+	if (!_h || !_h->tail) {
347
+		LM_ERR("invalid parameter value\n");
348
+		return;
349
+	}
350
+
351
+	con = (struct pool_con*)_h->tail;
352
+	if (pool_remove(con) == 1) {
353
+		free_connection(con);
354
+	}
355
+
356
+	pkg_free(_h);
357
+}
358
+
359
+
360
+
361
+/*! \brief
362
+ * Get version of a table
363
+ * \param dbf
364
+ * \param connection
365
+ * \param table
366
+ * \return If there is no row for the given table, return version 0
367
+ */
368
+int db_table_version(const db_func_t* dbf, db1_con_t* connection, const str* table)
369
+{
370
+	db_key_t key[1], col[1];
371
+	db_val_t val[1];
372
+	db1_res_t* res = NULL;
373
+	db_val_t* ver = 0;
374
+	str *version = &version_table;
375
+	str tmp1 = str_init(TABLENAME_COLUMN);
376
+	str tmp2 = str_init(VERSION_COLUMN);
377
+	int ret;
378
+
379
+	if (!dbf||!connection || !table || !table->s) {
380
+		LM_CRIT("invalid parameter value\n");
381
+		return -1;
382
+	}
383
+
384
+	if (dbf->use_table(connection, version) < 0) {
385
+		LM_ERR("error while changing table\n");
386
+		return -1;
387
+	}
388
+	key[0] = &tmp1;
389
+
390
+	VAL_TYPE(val) = DB1_STR;
391
+	VAL_NULL(val) = 0;
392
+	VAL_STR(val) = *table;
393
+	
394
+	col[0] = &tmp2;
395
+	
396
+	if (dbf->query(connection, key, 0, val, col, 1, 1, 0, &res) < 0) {
397
+		LM_ERR("error in db_query\n");
398
+		return -1;
399
+	}
400
+
401
+	if (RES_ROW_N(res) == 0) {
402
+		LM_DBG("no row for table %.*s found\n",
403
+			table->len, ZSW(table->s));
404
+		return 0;
405
+	}
406
+
407
+	if (RES_ROW_N(res) != 1) {
408
+		LM_ERR("invalid number of rows received:"
409
+			" %d, %.*s\n", RES_ROW_N(res), table->len, ZSW(table->s));
410
+		dbf->free_result(connection, res);
411
+		return -1;
412
+	}
413
+
414
+	ver = ROW_VALUES(RES_ROWS(res));
415
+	if ( VAL_TYPE(ver)!=DB1_INT || VAL_NULL(ver) ) {
416
+		LM_ERR("invalid type (%d) or nul (%d) version "
417
+			"columns for %.*s\n", VAL_TYPE(ver), VAL_NULL(ver),
418
+			table->len, ZSW(table->s));
419
+		dbf->free_result(connection, res);
420
+		return -1;
421
+	}
422
+
423
+	ret = VAL_INT(ver);
424
+	dbf->free_result(connection, res);
425
+	return ret;
426
+}
427
+
428
+/*! \brief
429
+ * Check the table version
430
+ * 0 means ok, -1 means an error occurred
431
+ */
432
+int db_check_table_version(db_func_t* dbf, db1_con_t* dbh, const str* table, const unsigned int version)
433
+{
434
+	int ver = db_table_version(dbf, dbh, table);
435
+	if (ver < 0) {
436
+		LM_ERR("querying version for table %.*s\n", table->len, table->s);
437
+		return -1;
438
+	} else if (ver != version) {
439
+		LM_ERR("invalid version %d for table %.*s found, expected %d (check table structure and table \"version\")\n", ver, table->len, table->s, version);
440
+		return -1;
441
+	}
442
+	return 0;
443
+}
444
+
445
+/*! \brief
446
+ * Store name of table that will be used by
447
+ * subsequent database functions
448
+ */
449
+int db_use_table(db1_con_t* _h, const str* _t)
450
+{
451
+	if (!_h || !_t || !_t->s) {
452
+		LM_ERR("invalid parameter value\n");
453
+		return -1;
454
+	}
455
+
456
+	CON_TABLE(_h) = _t;
457
+	return 0;
458
+}
459
+
460
+
461
+/*! \brief Generic query helper for load bulk data
462
+ *
463
+ * Generic query helper method for load bulk data, e.g. lcr tables
464
+ * \param binding database module binding
465
+ * \param handle database connection
466
+ * \param name database table name
467
+ * \param cols queried columns
468
+ * \param count number of queried columns
469
+ * \param strict if set to 1 an error is returned when no data could be loaded,
470
+    otherwise just a warning is logged
471
+ * \param res database result, unchanged on failure and if no data could be found
472
+ * \return 0 if the query was run successful, -1 otherwise
473
+ */
474
+int db_load_bulk_data(db_func_t* binding, db1_con_t* handle, str* name, db_key_t* cols,
475
+		      unsigned int count, unsigned int strict, db1_res_t* res)
476
+{
477
+	if (binding == NULL) {
478
+		LM_ERR("invalid database module binding\n");
479
+		return -1;
480
+	}
481
+
482
+	if(handle == NULL) {
483
+		LM_ERR("invalid database handle\n");
484
+		return -1;
485
+	}
486
+
487
+	if (binding->use_table(handle, name) < 0) {
488
+		LM_ERR("error in use_table for database\n");
489
+		return -1;
490
+	}
491
+
492
+	/* select the whole table and all the columns */
493
+	if(binding->query(handle, 0, 0, 0, cols, 0, count, 0, &res) < 0) {
494
+		LM_ERR("error while querying database\n");
495
+		return -1;
496
+	}
497
+
498
+	if(RES_ROW_N(res) == 0) {
499
+		binding->free_result(handle, res);
500
+		if (strict == 1) {
501
+			LM_ERR("no data in the database table %.*s\n", name->len, name->s);
502
+			return -1;
503
+		} else {
504
+			LM_WARN("no data in the database table %.*s, use an empty set\n", name->len, name->s);
505
+			return 0;
506
+		}
507
+	}
508
+
509
+	return 0;
510
+}
511
+
512
+/**
513
+ * \brief DB API init function.
514
+ *
515
+ * This function must be executed by DB connector modules at load time to
516
+ * initialize the internals of DB API library.
517
+ * \return returns 0 on successful initialization, -1 on error.
518
+ */
519
+int db_api_init(void)
520
+{
521
+	if(db_query_init()<0)
522
+		return -1;
523
+	return 0;
524
+}