RTS API Documentation  1.10.11
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-1);
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_open_v2(filename, ppDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI, NULL);
56 }
57 
59 {
60  return sqlite3_close(db);
61 }
62 
63 SWITCH_DECLARE(const unsigned char *) switch_core_db_column_text(switch_core_db_stmt_t *stmt, int iCol)
64 {
65  return sqlite3_column_text(stmt, iCol);
66 }
67 
69 {
70  return sqlite3_column_name(stmt, N);
71 }
72 
74 {
75  return sqlite3_column_count(pStmt);
76 }
77 
79 {
80  return sqlite3_errmsg(db);
81 }
82 
83 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)
84 {
85  int ret = 0;
86  int sane = 300;
87  char *err = NULL;
88 
89  while (--sane > 0) {
90  ret = sqlite3_exec(db, sql, callback, data, &err);
91  if (ret == SQLITE_BUSY || ret == SQLITE_LOCKED) {
92  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SQLite is %s, sane=%d [%s]\n", (ret == SQLITE_BUSY ? "BUSY" : "LOCKED"), sane, sql);
93  if (sane > 1) {
95  switch_yield(100000);
96  continue;
97  }
98  } else {
99  break;
100  }
101  }
102 
103  if (errmsg) {
104  *errmsg = err;
105  } else if (err) {
106  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s]\n", err);
107  switch_core_db_free(err);
108  err = NULL;
109  }
110 
111  return ret;
112 }
113 
115 {
116  return sqlite3_finalize(pStmt);
117 }
118 
119 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)
120 {
121  return sqlite3_prepare(db, zSql, nBytes, ppStmt, pzTail);
122 }
123 
125 {
126  return sqlite3_step(stmt);
127 }
128 
130 {
131  return sqlite3_reset(pStmt);
132 }
133 
135 {
136  return sqlite3_bind_int(pStmt, i, iValue);
137 }
138 
140 {
141  return sqlite3_bind_int64(pStmt, i, iValue);
142 }
143 
145 {
146  return sqlite3_bind_text(pStmt, i, zData, nData, xDel);
147 }
148 
150 {
151  return sqlite3_bind_double(pStmt, i, dValue);
152 }
153 
155 {
156  return sqlite3_last_insert_rowid(db);
157 }
158 
159 SWITCH_DECLARE(int) switch_core_db_get_table(switch_core_db_t *db, const char *sql, char ***resultp, int *nrow, int *ncolumn, char **errmsg)
160 {
161  return sqlite3_get_table(db, sql, resultp, nrow, ncolumn, errmsg);
162 }
163 
165 {
166  sqlite3_free_table(result);
167 }
168 
170 {
171  sqlite3_free(z);
172 }
173 
175 {
176  return sqlite3_changes(db);
177 }
178 
180 {
181  int ret = 0;
182  char *err = NULL;
183 
184 #ifdef SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION
185  sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, 0);
186  ret = sqlite3_load_extension(db, extension, 0, &err);
187 #else
188  sqlite3_enable_load_extension(db, 1);
189  ret = sqlite3_load_extension(db, extension, 0, &err);
190  sqlite3_enable_load_extension(db, 0);
191 #endif
192 
193  if (err) {
194  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "LOAD EXTENSION ERR [%s]\n", err);
195  switch_core_db_free(err);
196  err = NULL;
197  }
198  return ret;
199 }
200 
202  int db_ret;
203 
204  if ((db_ret = switch_core_db_exec(db, "PRAGMA synchronous=OFF;", NULL, NULL, NULL)) != SQLITE_OK) {
205  goto end;
206  }
207  if ((db_ret = switch_core_db_exec(db, "PRAGMA count_changes=OFF;", NULL, NULL, NULL)) != SQLITE_OK) {
208  goto end;
209  }
210  if ((db_ret = switch_core_db_exec(db, "PRAGMA temp_store=MEMORY;", NULL, NULL, NULL)) != SQLITE_OK) {
211  goto end;
212  }
213  if (!in_memory) {
214  if ((db_ret = switch_core_db_exec(db, "PRAGMA cache_size=8000;", NULL, NULL, NULL)) != SQLITE_OK) {
215  goto end;
216  }
217  } else {
218  if ((db_ret = switch_core_db_exec(db, "PRAGMA cache_size=-8192;", NULL, NULL, NULL)) != SQLITE_OK) {
219  goto end;
220  }
221  if ((db_ret = switch_core_db_exec(db, "PRAGMA journal_mode=OFF;", NULL, NULL, NULL)) != SQLITE_OK) {
222  goto end;
223  }
224  }
225 
226 end:
227  return db_ret;
228 }
229 
231 {
232  switch_core_db_t *db;
233  char path[1024];
234  int db_ret;
235 
236  db_pick_path(filename, path, sizeof(path));
237  if ((db_ret = switch_core_db_open(path, &db)) != SQLITE_OK) {
238  goto end;
239  }
240  if ((db_ret = switch_core_db_connection_setup(db, SWITCH_FALSE)) != SQLITE_OK) {
241  goto end;
242  }
243 
244 end:
245  if (db_ret != SQLITE_OK) {
248  db = NULL;
249  }
250  return db;
251 }
252 
254 {
255  switch_core_db_t *db;
256  int db_ret;
257 
258  if ((db_ret = switch_core_db_open_v2(uri, &db)) != SQLITE_OK) {
259  goto end;
260  }
261  if ((db_ret = switch_core_db_connection_setup(db, SWITCH_TRUE)) != SQLITE_OK) {
262  goto end;
263  }
264 
265 end:
266  if (db_ret != SQLITE_OK) {
269  db = NULL;
270  }
271  return db;
272 }
273 
274 SWITCH_DECLARE(void) switch_core_db_test_reactive(switch_core_db_t *db, char *test_sql, char *drop_sql, char *reactive_sql)
275 {
276  char *errmsg;
277 
279  return;
280  }
281 
283  switch_core_db_exec(db, test_sql, NULL, NULL, NULL);
284  return;
285  }
286 
287 
288  if (db) {
289  if (test_sql) {
290  switch_core_db_exec(db, test_sql, NULL, NULL, &errmsg);
291 
292  if (errmsg) {
293  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL ERR [%s]\n[%s]\nAuto Generating Table!\n", errmsg, test_sql);
294  switch_core_db_free(errmsg);
295  errmsg = NULL;
296  if (drop_sql) {
297  switch_core_db_exec(db, drop_sql, NULL, NULL, &errmsg);
298  }
299  if (errmsg) {
300  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL ERR [%s]\n[%s]\n", errmsg, reactive_sql);
301  switch_core_db_free(errmsg);
302  errmsg = NULL;
303  }
304  switch_core_db_exec(db, reactive_sql, NULL, NULL, &errmsg);
305  if (errmsg) {
306  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL ERR [%s]\n[%s]\n", errmsg, reactive_sql);
307  switch_core_db_free(errmsg);
308  errmsg = NULL;
309  }
310  }
311  }
312  }
313 
314 }
315 
316 
318 {
319  char *errmsg;
321  uint8_t forever = 0;
322  unsigned begin_retries = 100;
323  uint8_t again = 0;
324 
325  if (!retries) {
326  forever = 1;
327  retries = 1000;
328  }
329 
330  again:
331 
332  while (begin_retries > 0) {
333  again = 0;
334 
335  switch_core_db_exec(db, "BEGIN", NULL, NULL, &errmsg);
336 
337  if (errmsg) {
338  begin_retries--;
339  if (strstr(errmsg, "cannot start a transaction within a transaction")) {
340  again = 1;
341  } else {
342  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL Retry [%s]\n", errmsg);
343  }
344  switch_core_db_free(errmsg);
345  errmsg = NULL;
346 
347  if (again) {
348  switch_core_db_exec(db, "COMMIT", NULL, NULL, NULL);
349  goto again;
350  }
351 
352  switch_yield(100000);
353 
354  if (begin_retries == 0) {
355  goto done;
356  }
357  } else {
358  break;
359  }
360 
361  }
362 
363  while (retries > 0) {
364  switch_core_db_exec(db, sql, NULL, NULL, &errmsg);
365  if (errmsg) {
366  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s]\n", errmsg);
367  switch_core_db_free(errmsg);
368  errmsg = NULL;
369  switch_yield(100000);
370  retries--;
371  if (retries == 0 && forever) {
372  retries = 1000;
373  continue;
374  }
375  } else {
376  status = SWITCH_STATUS_SUCCESS;
377  break;
378  }
379  }
380 
381  done:
382 
383  switch_core_db_exec(db, "COMMIT", NULL, NULL, NULL);
384 
385  return status;
386 }
387 
389 {
390  char *errmsg;
392  uint8_t forever = 0;
393 
394  if (!retries) {
395  forever = 1;
396  retries = 1000;
397  }
398 
399  while (retries > 0) {
400  switch_core_db_exec(db, sql, NULL, NULL, &errmsg);
401  if (errmsg) {
402  //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s]\n", errmsg);
403  switch_core_db_free(errmsg);
404  switch_yield(100000);
405  retries--;
406  if (retries == 0 && forever) {
407  retries = 1000;
408  continue;
409  }
410  } else {
411  status = SWITCH_STATUS_SUCCESS;
412  break;
413  }
414  }
415 
416  return status;
417 }
418 
419 
420 
421 /* For Emacs:
422  * Local Variables:
423  * mode:c
424  * indent-tabs-mode:t
425  * tab-width:4
426  * c-basic-offset:4
427  * End:
428  * For VIM:
429  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
430  */
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)
switch_bool_t
Definition: switch_types.h:437
void(* switch_core_db_destructor_type_t)(void *)
const char * switch_core_db_column_name(switch_core_db_stmt_t *stmt, int N)
switch_core_db_t * switch_core_db_open_in_memory(const char *uri)
Open a core db (SQLite) in-memory.
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_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:86
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:124
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:998
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_open_v2(const char *filename, switch_core_db_t **ppDb)
int(* switch_core_db_callback_func_t)(void *pArg, int argc, char **argv, char **columnNames)
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:82
static int switch_core_db_connection_setup(switch_core_db_t *db, switch_bool_t in_memory)
int switch_core_db_bind_double(switch_core_db_stmt_t *pStmt, int i, double dValue)
switch_status_t
Common return values.
const char *const const char *const path
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)
const char * filename
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:693
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)
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)