1 /*
2  * BDB Database Driver for SER
3  *
4  * Copyright (C) 2008 iptelorg GmbH
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio is free software; you can redistribute it and/or modify it under the
9  * terms of the GNU General Public License as published by the Free Software
10  * Foundation; either version 2 of the License, or (at your option) any later
11  * version.
12  *
13  * Kamailio is distributed in the hope that it will be useful, but WITHOUT ANY
14  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22 
23 /** \addtogroup bdb
24  * @{
25  */
26 
27 /*! \file
28  * Functions related to connections to BDB.
29  *
30  * \ingroup database
31  */
32 
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #include "../../core/mem/mem.h"
37 #include "../../core/dprint.h"
38 #include "../../core/ut.h"
39 
40 #include "bdb_con.h"
41 #include "bdb_uri.h"
42 #include "bdb_lib.h"
43 
44 /** Free all memory allocated for a bdb_con structure.
45  * This function function frees all memory that is in use by
46  * a bdb_con structure.
47  * @param con A generic db_con connection structure.
48  * @param payload BDB specific payload to be freed.
49  */
bdb_con_free(db_con_t * con,bdb_con_t * payload)50 static void bdb_con_free(db_con_t *con, bdb_con_t *payload)
51 {
52 	if(!payload)
53 		return;
54 
55 	/* Delete the structure only if there are no more references
56 	 * to it in the connection pool
57 	 */
58 	if(db_pool_remove((db_pool_entry_t *)payload) == 0)
59 		return;
60 
61 	db_pool_entry_free(&payload->gen);
62 
63 	/* destroy and free BDB env */
64 	pkg_free(payload);
65 }
66 
67 
bdb_con(db_con_t * con)68 int bdb_con(db_con_t *con)
69 {
70 	bdb_con_t *bcon;
71 	bdb_uri_t *buri;
72 
73 	buri = DB_GET_PAYLOAD(con->uri);
74 
75 	/* First try to lookup the connection in the connection pool and
76 	 * re-use it if a match is found
77 	 */
78 	bcon = (bdb_con_t *)db_pool_get(con->uri);
79 	if(bcon) {
80 		DBG("bdb: Connection to %s found in connection pool\n", buri->uri);
81 		goto found;
82 	}
83 
84 	bcon = (bdb_con_t *)pkg_malloc(sizeof(bdb_con_t));
85 	if(!bcon) {
86 		ERR("bdb: No memory left\n");
87 		goto error;
88 	}
89 	memset(bcon, '\0', sizeof(bdb_con_t));
90 	if(db_pool_entry_init(&bcon->gen, bdb_con_free, con->uri) < 0)
91 		goto error;
92 
93 	DBG("bdb: Preparing new connection to %s\n", buri->uri);
94 	if(bdb_is_database(buri->path.s) != 0) {
95 		ERR("bdb: database [%.*s] does not exists!\n", buri->path.len,
96 				buri->path.s);
97 		goto error;
98 	}
99 
100 	/* Put the newly created BDB connection into the pool */
101 	db_pool_put((struct db_pool_entry *)bcon);
102 	DBG("bdb: Connection stored in connection pool\n");
103 
104 found:
105 	/* Attach driver payload to the db_con structure and set connect and
106 	 * disconnect functions
107 	 */
108 	DB_SET_PAYLOAD(con, bcon);
109 	con->connect = bdb_con_connect;
110 	con->disconnect = bdb_con_disconnect;
111 	return 0;
112 
113 error:
114 	if(bcon) {
115 		db_pool_entry_free(&bcon->gen);
116 		pkg_free(bcon);
117 	}
118 	return -1;
119 }
120 
121 
bdb_con_connect(db_con_t * con)122 int bdb_con_connect(db_con_t *con)
123 {
124 	bdb_con_t *bcon;
125 	bdb_uri_t *buri;
126 
127 	bcon = DB_GET_PAYLOAD(con);
128 	buri = DB_GET_PAYLOAD(con->uri);
129 
130 	/* Do not reconnect already connected connections */
131 	if(bcon->flags & BDB_CONNECTED)
132 		return 0;
133 
134 	DBG("bdb: Connecting to %s\n", buri->uri);
135 
136 	/* create BDB environment */
137 	bcon->dbp = bdblib_get_db(&buri->path);
138 	if(bcon->dbp == NULL) {
139 		ERR("bdb: error binding to DB %s\n", buri->uri);
140 		return -1;
141 	}
142 
143 	DBG("bdb: Successfully bound to %s\n", buri->uri);
144 	bcon->flags |= BDB_CONNECTED;
145 	return 0;
146 }
147 
148 
bdb_con_disconnect(db_con_t * con)149 void bdb_con_disconnect(db_con_t *con)
150 {
151 	bdb_con_t *bcon;
152 	bdb_uri_t *buri;
153 
154 	bcon = DB_GET_PAYLOAD(con);
155 	buri = DB_GET_PAYLOAD(con->uri);
156 
157 	if((bcon->flags & BDB_CONNECTED) == 0)
158 		return;
159 
160 	DBG("bdb: Unbinding from %s\n", buri->uri);
161 	if(bcon->dbp == NULL) {
162 		bcon->flags &= ~BDB_CONNECTED;
163 		return;
164 	}
165 
166 	bdblib_close(bcon->dbp, &buri->path);
167 	bcon->dbp = 0;
168 
169 	bcon->flags &= ~BDB_CONNECTED;
170 }
171 
172 
173 /** @} */
174