FreeSWITCH API Documentation  1.7.0
switch_core_db.c
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Michael Jerris <mike@jerris.com>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Michael Jerris <mike@jerris.com>
27  *
28  *
29  * switch_core_db.c -- sqlite wrapper and extensions
30  *
31  */
32 
33 #include <switch.h>
35 
36 #include <sqlite3.h>
37 
38 static void db_pick_path(const char *dbname, char *buf, switch_size_t size)
39 {
40  memset(buf, 0, size);
41  if (switch_is_file_path(dbname)) {
42  strncpy(buf, dbname, size);
43  } else {
44  switch_snprintf(buf, size, "%s%s%s.db", SWITCH_GLOBAL_dirs.db_dir, SWITCH_PATH_SEPARATOR, dbname);
45  }
46 }
47 
49 {
50  return sqlite3_open(filename, ppDb);
51 }
52 
54 {
55  return sqlite3_close(db);
56 }
57 
58 SWITCH_DECLARE(const unsigned char *) switch_core_db_column_text(switch_core_db_stmt_t *stmt, int iCol)
59 {
60  const unsigned char *txt = sqlite3_column_text(stmt, iCol);
61 
62  if (!strcasecmp((char *) stmt, "(null)")) {
63  memset(stmt, 0, 1);
64  txt = NULL;
65  }
66 
67  return txt;
68 
69 }
70 
72 {
73  return sqlite3_column_name(stmt, N);
74 }
75 
77 {
78  return sqlite3_column_count(pStmt);
79 }
80 
82 {
83  return sqlite3_errmsg(db);
84 }
85 
86 SWITCH_DECLARE(int) switch_core_db_exec(switch_core_db_t *db, const char *sql, switch_core_db_callback_func_t callback, void *data, char **errmsg)
87 {
88  int ret = 0;
89  int sane = 300;
90  char *err = NULL;
91 
92  while (--sane > 0) {
93  ret = sqlite3_exec(db, sql, callback, data, &err);
94  if (ret == SQLITE_BUSY || ret == SQLITE_LOCKED) {
95  if (sane > 1) {
97  switch_yield(100000);
98  continue;
99  }
100  } else {
101  break;
102  }
103  }
104 
105  if (errmsg) {
106  *errmsg = err;
107  } else if (err) {
108  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s]\n", err);
109  switch_core_db_free(err);
110  err = NULL;
111  }
112 
113  return ret;
114 }
115 
117 {
118  return sqlite3_finalize(pStmt);
119 }
120 
121 SWITCH_DECLARE(int) switch_core_db_prepare(switch_core_db_t *db, const char *zSql, int nBytes, switch_core_db_stmt_t **ppStmt, const char **pzTail)
122 {
123  return sqlite3_prepare(db, zSql, nBytes, ppStmt, pzTail);
124 }
125 
127 {
128  return sqlite3_step(stmt);
129 }
130 
132 {
133  return sqlite3_reset(pStmt);
134 }
135 
137 {
138  return sqlite3_bind_int(pStmt, i, iValue);
139 }
140 
142 {
143  return sqlite3_bind_int64(pStmt, i, iValue);
144 }
145 
147 {
148  return sqlite3_bind_text(pStmt, i, zData, nData, xDel);
149 }
150 
152 {
153  return sqlite3_bind_double(pStmt, i, dValue);
154 }
155 
157 {
158  return sqlite3_last_insert_rowid(db);
159 }
160 
161 SWITCH_DECLARE(int) switch_core_db_get_table(switch_core_db_t *db, const char *sql, char ***resultp, int *nrow, int *ncolumn, char **errmsg)
162 {
163  return sqlite3_get_table(db, sql, resultp, nrow, ncolumn, errmsg);
164 }
165 
167 {
168  sqlite3_free_table(result);
169 }
170 
172 {
173  sqlite3_free(z);
174 }
175 
177 {
178  return sqlite3_changes(db);
179 }
180 
182 {
183  int ret = 0;
184  char *err = NULL;
185 
186  sqlite3_enable_load_extension(db, 1);
187  ret = sqlite3_load_extension(db, extension, 0, &err);
188  sqlite3_enable_load_extension(db, 0);
189 
190  if (err) {
191  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "LOAD EXTENSION ERR [%s]\n", err);
192  switch_core_db_free(err);
193  err = NULL;
194  }
195  return ret;
196 }
197 
199 {
200  switch_core_db_t *db;
201  char path[1024];
202  int db_ret;
203 
204  db_pick_path(filename, path, sizeof(path));
205  if ((db_ret = switch_core_db_open(path, &db)) != SQLITE_OK) {
206  goto end;
207  }
208  if ((db_ret = switch_core_db_exec(db, "PRAGMA synchronous=OFF;", NULL, NULL, NULL) != SQLITE_OK)) {
209  goto end;
210  }
211  if ((db_ret = switch_core_db_exec(db, "PRAGMA count_changes=OFF;", NULL, NULL, NULL) != SQLITE_OK)) {
212  goto end;
213  }
214  if ((db_ret = switch_core_db_exec(db, "PRAGMA cache_size=8000;", NULL, NULL, NULL) != SQLITE_OK)) {
215  goto end;
216  }
217  if ((db_ret = switch_core_db_exec(db, "PRAGMA temp_store=MEMORY;", NULL, NULL, NULL) != SQLITE_OK)) {
218  goto end;
219  }
220 
221 end:
222  if (db_ret != SQLITE_OK) {
225  db = NULL;
226  }
227  return db;
228 }
229 
230 SWITCH_DECLARE(void) switch_core_db_test_reactive(switch_core_db_t *db, char *test_sql, char *drop_sql, char *reactive_sql)
231 {
232  char *errmsg;
233 
235  return;
236  }
237 
239  switch_core_db_exec(db, test_sql, NULL, NULL, NULL);
240  return;
241  }
242 
243 
244  if (db) {
245  if (test_sql) {
246  switch_core_db_exec(db, test_sql, NULL, NULL, &errmsg);
247 
248  if (errmsg) {
249  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL ERR [%s]\n[%s]\nAuto Generating Table!\n", errmsg, test_sql);
250  switch_core_db_free(errmsg);
251  errmsg = NULL;
252  if (drop_sql) {
253  switch_core_db_exec(db, drop_sql, NULL, NULL, &errmsg);
254  }
255  if (errmsg) {
256  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL ERR [%s]\n[%s]\n", errmsg, reactive_sql);
257  switch_core_db_free(errmsg);
258  errmsg = NULL;
259  }
260  switch_core_db_exec(db, reactive_sql, NULL, NULL, &errmsg);
261  if (errmsg) {
262  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL ERR [%s]\n[%s]\n", errmsg, reactive_sql);
263  switch_core_db_free(errmsg);
264  errmsg = NULL;
265  }
266  }
267  }
268  }
269 
270 }
271 
272 
274 {
275  char *errmsg;
277  uint8_t forever = 0;
278  unsigned begin_retries = 100;
279  uint8_t again = 0;
280 
281  if (!retries) {
282  forever = 1;
283  retries = 1000;
284  }
285 
286  again:
287 
288  while (begin_retries > 0) {
289  again = 0;
290 
291  switch_core_db_exec(db, "BEGIN", NULL, NULL, &errmsg);
292 
293  if (errmsg) {
294  begin_retries--;
295  if (strstr(errmsg, "cannot start a transaction within a transaction")) {
296  again = 1;
297  } else {
298  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL Retry [%s]\n", errmsg);
299  }
300  switch_core_db_free(errmsg);
301  errmsg = NULL;
302 
303  if (again) {
304  switch_core_db_exec(db, "COMMIT", NULL, NULL, NULL);
305  goto again;
306  }
307 
308  switch_yield(100000);
309 
310  if (begin_retries == 0) {
311  goto done;
312  }
313  } else {
314  break;
315  }
316 
317  }
318 
319  while (retries > 0) {
320  switch_core_db_exec(db, sql, NULL, NULL, &errmsg);
321  if (errmsg) {
322  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s]\n", errmsg);
323  switch_core_db_free(errmsg);
324  errmsg = NULL;
325  switch_yield(100000);
326  retries--;
327  if (retries == 0 && forever) {
328  retries = 1000;
329  continue;
330  }
331  } else {
332  status = SWITCH_STATUS_SUCCESS;
333  break;
334  }
335  }
336 
337  done:
338 
339  switch_core_db_exec(db, "COMMIT", NULL, NULL, NULL);
340 
341  return status;
342 }
343 
345 {
346  char *errmsg;
348  uint8_t forever = 0;
349 
350  if (!retries) {
351  forever = 1;
352  retries = 1000;
353  }
354 
355  while (retries > 0) {
356  switch_core_db_exec(db, sql, NULL, NULL, &errmsg);
357  if (errmsg) {
358  //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s]\n", errmsg);
359  switch_core_db_free(errmsg);
360  switch_yield(100000);
361  retries--;
362  if (retries == 0 && forever) {
363  retries = 1000;
364  continue;
365  }
366  } else {
367  status = SWITCH_STATUS_SUCCESS;
368  break;
369  }
370  }
371 
372  return status;
373 }
374 
375 
376 
377 /* For Emacs:
378  * Local Variables:
379  * mode:c
380  * indent-tabs-mode:t
381  * tab-width:4
382  * c-basic-offset:4
383  * End:
384  * For VIM:
385  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
386  */
void switch_core_db_free_table(char **result)
#define SWITCH_CHANNEL_LOG
const char * switch_core_db_errmsg(switch_core_db_t *db)
int switch_core_db_get_table(switch_core_db_t *db, const char *sql, char ***resultp, int *nrow, int *ncolumn, char **errmsg)
const char * switch_core_db_column_name(switch_core_db_stmt_t *stmt, int N)
int switch_core_db_close(switch_core_db_t *db)
switch_status_t switch_core_db_persistant_execute(switch_core_db_t *db, char *sql, uint32_t retries)
Execute a sql stmt until it is accepted.
int(* switch_core_db_callback_func_t)(void *pArg, int argc, char **argv, char **columnNames)
int switch_snprintf(_Out_z_cap_(len) char *buf, _In_ switch_size_t len, _In_z_ _Printf_format_string_ const char *format,...)
int switch_core_db_finalize(switch_core_db_stmt_t *pStmt)
struct switch_runtime runtime
Definition: switch_core.c:64
int switch_core_db_step(switch_core_db_stmt_t *stmt)
int switch_core_db_exec(switch_core_db_t *db, const char *sql, switch_core_db_callback_func_t callback, void *data, char **errmsg)
int switch_core_db_bind_text(switch_core_db_stmt_t *pStmt, int i, const char *zData, int nData, switch_core_db_destructor_type_t xDel)
#define SWITCH_PATH_SEPARATOR
Definition: switch_types.h:122
switch_byte_t switch_byte_t * buf
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
int switch_core_db_load_extension(switch_core_db_t *db, const char *extension)
void switch_core_db_test_reactive(switch_core_db_t *db, char *test_sql, char *drop_sql, char *reactive_sql)
perform a test query then perform a reactive query if the first one fails
uintptr_t switch_size_t
int switch_core_db_reset(switch_core_db_stmt_t *pStmt)
switch_status_t switch_core_db_persistant_execute_trans(switch_core_db_t *db, char *sql, uint32_t retries)
switch_directories SWITCH_GLOBAL_dirs
Definition: switch_core.c:60
int switch_core_db_bind_double(switch_core_db_stmt_t *pStmt, int i, double dValue)
switch_status_t
Common return values.
int64_t switch_core_db_last_insert_rowid(switch_core_db_t *db)
struct sqlite3 switch_core_db_t
int switch_core_db_open(const char *filename, switch_core_db_t **ppDb)
Main Library Header.
static switch_bool_t switch_is_file_path(const char *file)
#define SWITCH_DECLARE(type)
void switch_core_db_free(char *z)
struct sqlite3_stmt switch_core_db_stmt_t
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:624
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
int switch_core_db_changes(switch_core_db_t *db)
int switch_core_db_column_count(switch_core_db_stmt_t *pStmt)
const unsigned char * switch_core_db_column_text(switch_core_db_stmt_t *stmt, int iCol)
int switch_core_db_bind_int64(switch_core_db_stmt_t *pStmt, int i, int64_t iValue)
char * filename
switch_core_db_t * switch_core_db_open_file(const char *filename)
Open a core db (SQLite) file.
static void db_pick_path(const char *dbname, char *buf, switch_size_t size)
memset(buf, 0, buflen)
int switch_core_db_prepare(switch_core_db_t *db, const char *zSql, int nBytes, switch_core_db_stmt_t **ppStmt, const char **pzTail)
int switch_core_db_bind_int(switch_core_db_stmt_t *pStmt, int i, int iValue)
void(* switch_core_db_destructor_type_t)(void *)