RTS API Documentation  1.10.11
switch_core_sqldb.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  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  * Michael Jerris <mike@jerris.com>
28  * Paul D. Tinsley <pdt at jackhammer.org>
29  * Emmanuel Schmidbauer <eschmidbauer@gmail.com>
30  * Andrey Volk <andywolk@gmail.com>
31  *
32  *
33  * switch_core_sqldb.c -- Main Core Library (statistics tracker)
34  *
35  */
36 
37 #include <switch.h>
39 
40 #define SWITCH_SQL_QUEUE_LEN 100000
41 #define SWITCH_SQL_QUEUE_PAUSE_LEN 90000
42 
47  time_t last_used;
50  int32_t flags;
51  unsigned long hash;
52  unsigned long thread_hash;
55  uint32_t use_count;
56  uint64_t total_used_count;
58 };
59 
60 static struct {
68  uint32_t total_handles;
72  int paused;
73 } sql_manager;
74 
75 
76 static void switch_core_sqldb_start_thread(void);
77 static void switch_core_sqldb_stop_thread(void);
78 
79 #define database_interface_handle_callback_exec(database_interface, dih, sql, callback, pdata, err) database_interface->callback_exec_detailed(__FILE__, (char *)__SWITCH_FUNC__, __LINE__, dih, sql, callback, pdata, err)
80 #define database_interface_handle_exec(database_interface, dih, sql, err) database_interface->exec_detailed(__FILE__, (char *)__SWITCH_FUNC__, __LINE__, dih, sql, err)
81 
83 {
84  switch_cache_db_handle_t *new_dbh = NULL;
85  switch_memory_pool_t *pool = NULL;
86 
88  new_dbh = switch_core_alloc(pool, sizeof(*new_dbh));
89  new_dbh->pool = pool;
90  new_dbh->type = type;
91  switch_mutex_init(&new_dbh->mutex, SWITCH_MUTEX_NESTED, new_dbh->pool);
92 
93  return new_dbh;
94 }
95 
97 {
98  if (dbh && *dbh && (*dbh)->pool) {
99  switch_core_destroy_memory_pool(&(*dbh)->pool);
100  *dbh = NULL;
101  }
102 }
103 
104 static void add_handle(switch_cache_db_handle_t *dbh, const char *db_str, const char *db_callsite_str, const char *thread_str)
105 {
106  switch_ssize_t hlen = -1;
107 
108  switch_mutex_lock(sql_manager.dbh_mutex);
109  switch_mutex_lock(dbh->mutex);
110 
111  switch_set_string(dbh->creator, db_callsite_str);
112 
113  switch_set_string(dbh->name, db_str);
114  dbh->hash = switch_ci_hashfunc_default(db_str, &hlen);
115  dbh->thread_hash = switch_ci_hashfunc_default(thread_str, &hlen);
116 
117  dbh->use_count++;
118  dbh->total_used_count++;
119  dbh->next = sql_manager.handle_pool;
120 
121  sql_manager.handle_pool = dbh;
122  sql_manager.total_handles++;
123  sql_manager.total_used_handles++;
124  switch_mutex_unlock(sql_manager.dbh_mutex);
125 }
126 
128 {
129  switch_cache_db_handle_t *dbh_ptr, *last = NULL;
130 
131  switch_mutex_lock(sql_manager.dbh_mutex);
132  for (dbh_ptr = sql_manager.handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) {
133  if (dbh_ptr == dbh) {
134  if (last) {
135  last->next = dbh_ptr->next;
136  } else {
137  sql_manager.handle_pool = dbh_ptr->next;
138  }
139  sql_manager.total_handles--;
140  break;
141  }
142 
143  last = dbh_ptr;
144  }
145  switch_mutex_unlock(sql_manager.dbh_mutex);
146 }
147 
149 {
150  switch_cache_db_handle_t *dbh_ptr = NULL;
151 
152  switch_mutex_lock(sql_manager.dbh_mutex);
153 
154 top:
155 
156  for (dbh_ptr = sql_manager.handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) {
158  if (dbh_ptr->type != SCDB_TYPE_DATABASE_INTERFACE) {
159  switch_mutex_unlock(dbh_ptr->mutex);
160  continue;
161  }
162 
163  if (dbh_ptr->native_handle.database_interface_dbh->connection_options.database_interface != database_interface) {
164  switch_mutex_unlock(dbh_ptr->mutex);
165  continue;
166  }
167 
168  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Dropping DB connection %s\n", dbh_ptr->name);
169 
170  database_interface->handle_destroy(&dbh_ptr->native_handle.database_interface_dbh);
171 
172  del_handle(dbh_ptr);
173  switch_mutex_unlock(dbh_ptr->mutex);
174  destroy_handle(&dbh_ptr);
175  goto top;
176  }
177  }
178 
179  switch_mutex_unlock(sql_manager.dbh_mutex);
180 }
181 
182 static switch_cache_db_handle_t *get_handle(const char *db_str, const char *user_str, const char *thread_str)
183 {
184  switch_ssize_t hlen = -1;
185  unsigned long hash = 0, thread_hash = 0;
186  switch_cache_db_handle_t *dbh_ptr, *r = NULL;
187 
188  hash = switch_ci_hashfunc_default(db_str, &hlen);
189  thread_hash = switch_ci_hashfunc_default(thread_str, &hlen);
190 
191  switch_mutex_lock(sql_manager.dbh_mutex);
192 
193  /* First loop allows a thread to use a handle multiple times sumiltaneously
194  but only if that handle is in use by the same thread. In that case use_count will be incremented.
195  This allows SQLite to read and write within a single thread, giving the same handle for both operations.
196  */
197  for (dbh_ptr = sql_manager.handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) {
198  if (dbh_ptr->thread_hash == thread_hash && dbh_ptr->hash == hash &&
200  r = dbh_ptr;
201  break;
202  }
203  }
204 
205  if (!r) {
206  /* If a handle idles, take it and associate with the thread.
207  If a handle is in use, skip and create new one.
208  */
209  for (dbh_ptr = sql_manager.handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) {
210  if (dbh_ptr->hash == hash && !dbh_ptr->use_count && !switch_test_flag(dbh_ptr, CDF_PRUNE) &&
212  r = dbh_ptr;
214  break;
215  }
216  }
217  }
218 
219  if (r) {
220  r->use_count++;
221  r->total_used_count++;
222  sql_manager.total_used_handles++;
223  switch_set_string(r->last_user, user_str);
224  }
225 
226  switch_mutex_unlock(sql_manager.dbh_mutex);
227 
228  return r;
229 
230 }
231 
232 /*!
233  \brief Open the default system database
234 */
235 SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t **dbh, const char *file, const char *func, int line)
236 {
237  switch_status_t r;
238  char *dsn;
239 
240  if (!sql_manager.manage) {
241  return SWITCH_STATUS_FALSE;
242  }
243 
244  if (!zstr(runtime.odbc_dsn)) {
245  dsn = runtime.odbc_dsn;
246  } else if (!zstr(runtime.dbname)) {
247  dsn = runtime.dbname;
248  } else {
249  dsn = "core";
250  }
251 
252  if ((r = _switch_cache_db_get_db_handle_dsn_ex(dbh, dsn, SWITCH_TRUE, file, func, line)) != SWITCH_STATUS_SUCCESS) {
253  *dbh = NULL;
254  }
255 
256  return r;
257 }
258 
259 #define SQL_CACHE_TIMEOUT 30
260 #define SQL_REG_TIMEOUT 15
261 
262 
263 static void sql_close(time_t prune)
264 {
266  int locked = 0;
267  int sanity = 10000;
268 
269  switch_mutex_lock(sql_manager.dbh_mutex);
270  top:
271  locked = 0;
272 
273  for (dbh = sql_manager.handle_pool; dbh; dbh = dbh->next) {
274  time_t diff = 0;
275 
276  if (prune > 0 && prune > dbh->last_used) {
277  diff = (time_t) prune - dbh->last_used;
278  }
279 
280  if (prune > 0 && (dbh->use_count || switch_test_flag(dbh, CDF_NONEXPIRING) || (diff < SQL_CACHE_TIMEOUT && !switch_test_flag(dbh, CDF_PRUNE)))) {
281  continue;
282  }
283 
285  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Dropping idle DB connection %s\n", dbh->name);
286 
287  switch (dbh->type) {
289  {
291  database_interface->handle_destroy(&dbh->native_handle.database_interface_dbh);
292  }
293  break;
294  case SCDB_TYPE_ODBC:
295  {
297  }
298  break;
299  case SCDB_TYPE_CORE_DB:
300  {
302  dbh->native_handle.core_db_dbh->handle = NULL;
303  }
304  break;
305  }
306 
307  del_handle(dbh);
309  destroy_handle(&dbh);
310  goto top;
311 
312  } else {
313  if (!prune) {
314  if (!sanity) {
315  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SANITY CHECK FAILED! Handle %s (%s;%s) was not properly released.\n",
316  dbh->name, dbh->creator, dbh->last_user);
317  } else {
318  locked++;
319  }
320  }
321  continue;
322  }
323 
324  }
325 
326  if (locked) {
327  if (!prune) {
329  if (sanity) sanity--;
330  }
331  goto top;
332  }
333 
334  switch_mutex_unlock(sql_manager.dbh_mutex);
335 }
336 
337 
339 {
340  return dbh->type;
341 }
342 
344 {
346 }
347 
348 
350 {
351  if (dbh && *dbh) {
352 
353  switch((*dbh)->type) {
355  {
356  switch_database_interface_t *database_interface = (*dbh)->native_handle.database_interface_dbh->connection_options.database_interface;
357  database_interface->flush((*dbh)->native_handle.database_interface_dbh);
358  }
359  break;
360  default:
361  break;
362  }
363 
364  (*dbh)->last_used = switch_epoch_time_now(NULL);
365  if ((*dbh)->use_count) {
366  --(*dbh)->use_count;
367  }
368 
369  switch_mutex_unlock((*dbh)->mutex);
370  *dbh = NULL;
371 
372  switch_mutex_lock(sql_manager.dbh_mutex);
373  sql_manager.total_used_handles--;
374  switch_mutex_unlock(sql_manager.dbh_mutex);
375  }
376 }
377 
378 
380 {
382 }
383 
384 #ifndef MIN
385 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
386 #endif
387 
389 {
391  switch_database_interface_t *database_interface;
392 
393  if (!dsn) {
394  status = SWITCH_STATUS_SUCCESS;
395  }
396  else {
397  char *colon_slashes = NULL;
398  if (NULL != (colon_slashes = strstr(dsn, "://")))
399  {
400  char prefix[16] = "";
401  strncpy(prefix, dsn, MIN(colon_slashes - dsn, 15));
402 
403  if (!strncasecmp(prefix, "odbc", 4)) {
405  }
406  else if (!strncasecmp(prefix, "sqlite", 6)) {
407  status = SWITCH_STATUS_SUCCESS;
408  }
409  else if ((database_interface = switch_loadable_module_get_database_interface(prefix, NULL))) {
410  status = SWITCH_STATUS_SUCCESS;
411  UNPROTECT_INTERFACE(database_interface);
412  }
413  }
414  else if (strchr(dsn + 2, ':')) {
415  status = SWITCH_STATUS_SUCCESS;
416  }
417  }
418 
419  return status;
420 }
421 
423 {
425 }
426 
428  const char *file, const char *func, int line)
429 {
430  return _switch_cache_db_get_db_handle_dsn_ex(dbh, dsn, SWITCH_FALSE, file, func, line);
431 }
432 
434  const char *file, const char *func, int line)
435 {
436  switch_cache_db_connection_options_t connection_options = { {0} };
438  switch_database_interface_t *database_interface = NULL;
439  char tmp[256] = "";
440  char *p;
442  int i;
443 
444  char *colon_slashes = NULL;
445  if ( NULL != (colon_slashes = strstr(dsn, "://")) )
446  {
447  char prefix[16] = "";
448  strncpy(prefix, dsn, MIN(colon_slashes - dsn, 15));
449 
450  if ((database_interface = switch_loadable_module_get_database_interface(prefix, NULL))) {
452  connection_options.database_interface_options.make_module_no_unloadable = make_module_no_unloadable;
453  connection_options.database_interface_options.database_interface = database_interface;
454  connection_options.database_interface_options.original_dsn = dsn;
455  connection_options.database_interface_options.connection_string = colon_slashes + 3;
456  strcpy(connection_options.database_interface_options.prefix, prefix);
457  UNPROTECT_INTERFACE(database_interface);
458  }
459  }
460 
461  if (!connection_options.database_interface_options.connection_string)
462  {
463  if (!strncasecmp(dsn, "sqlite://", 9)) {
464  type = SCDB_TYPE_CORE_DB;
465  connection_options.core_db_options.db_path = (char *)(dsn + 9);
466  if (!strncasecmp(connection_options.core_db_options.db_path, "memory://", 9)) {
467  connection_options.core_db_options.in_memory = SWITCH_TRUE;
468  connection_options.core_db_options.db_path = (char *)(connection_options.core_db_options.db_path + 9);
469  }
470  }
471  else if ((!(i = strncasecmp(dsn, "odbc://", 7))) || (strchr(dsn + 2, ':') && !colon_slashes)) {
472  type = SCDB_TYPE_ODBC;
473 
474  if (i) {
475  switch_set_string(tmp, dsn);
476  }
477  else {
478  switch_set_string(tmp, dsn + 7);
479  }
480 
481  connection_options.odbc_options.dsn = tmp;
482 
483  if ((p = strchr(tmp, ':'))) {
484  *p++ = '\0';
485  connection_options.odbc_options.user = p;
486 
487  if ((p = strchr(connection_options.odbc_options.user, ':'))) {
488  *p++ = '\0';
489  connection_options.odbc_options.pass = p;
490  }
491  }
492  }
493  else {
494  type = SCDB_TYPE_CORE_DB;
495  connection_options.core_db_options.db_path = (char *)dsn;
496  }
497  }
498 
499  status = _switch_cache_db_get_db_handle(dbh, type, &connection_options, file, func, line);
500 
501  if (status != SWITCH_STATUS_SUCCESS) *dbh = NULL;
502 
503  return status;
504 }
505 
506 
509  switch_cache_db_connection_options_t *connection_options,
510  const char *file, const char *func, int line)
511 {
513  char thread_str[CACHE_DB_LEN] = "";
514  char db_str[CACHE_DB_LEN] = "";
515  char db_callsite_str[CACHE_DB_LEN] = "";
516  switch_cache_db_handle_t *new_dbh = NULL;
517  int waiting = 0;
518  uint32_t yield_len = 100000, total_yield = 0;
519 
520  const char *db_name = NULL;
521  const char *odbc_user = NULL;
522  const char *odbc_pass = NULL;
523  const char *db_type = NULL;
524 
525  while(runtime.max_db_handles && sql_manager.total_handles >= runtime.max_db_handles && sql_manager.total_used_handles >= sql_manager.total_handles) {
526  if (!waiting++) {
527  switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_WARNING, "Max handles %u exceeded, blocking....\n",
529  }
530 
531  switch_yield(yield_len);
532  total_yield += yield_len;
533 
534  if (runtime.db_handle_timeout && total_yield > runtime.db_handle_timeout) {
535  switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "Error connecting\n");
536  *dbh = NULL;
537  return SWITCH_STATUS_FALSE;
538  }
539  }
540 
541  switch (type) {
543  {
544  db_name = connection_options->database_interface_options.connection_string;
545  odbc_user = NULL;
546  odbc_pass = NULL;
547  db_type = "database_interface";
548  }
549  break;
550  case SCDB_TYPE_ODBC:
551  {
552  db_name = connection_options->odbc_options.dsn;
553  odbc_user = connection_options->odbc_options.user;
554  odbc_pass = connection_options->odbc_options.pass;
555  db_type = "odbc";
556  }
557  break;
558  case SCDB_TYPE_CORE_DB:
559  {
560  db_name = connection_options->core_db_options.db_path;
561  odbc_user = NULL;
562  odbc_pass = NULL;
563  db_type = "core_db";
564  }
565  break;
566  }
567 
568  if (!db_name) {
569  return SWITCH_STATUS_FALSE;
570  }
571 
572  if (odbc_user || odbc_pass) {
573  snprintf(db_str, sizeof(db_str) - 1, "db=\"%s\";type=\"%s\"user=\"%s\";pass=\"%s\"", db_name, db_type, odbc_user, odbc_pass);
574  } else {
575  snprintf(db_str, sizeof(db_str) - 1, "db=\"%s\",type=\"%s\"", db_name, db_type);
576  }
577  snprintf(db_callsite_str, sizeof(db_callsite_str) - 1, "%s:%d", file, line);
578  snprintf(thread_str, sizeof(thread_str) - 1, "thread=\"%lu\"", (unsigned long) (intptr_t) self);
579 
580  if ((new_dbh = get_handle(db_str, db_callsite_str, thread_str))) {
581  if (type == SCDB_TYPE_DATABASE_INTERFACE) {
583  "Reuse Unused Cached DB handle %s [Database interface prefix: %s]\n", new_dbh->name, connection_options->database_interface_options.prefix);
584  } else {
586  "Reuse Unused Cached DB handle %s [%s]\n", new_dbh->name, switch_cache_db_type_name(new_dbh->type));
587  }
588  } else {
589  switch_core_db_t *db = NULL;
590  switch_odbc_handle_t *odbc_dbh = NULL;
591  switch_database_interface_handle_t *database_interface_dbh = NULL;
592 
593  switch (type) {
595  {
596  switch_database_interface_t *database_interface = connection_options->database_interface_options.database_interface;
597 
598  if (SWITCH_STATUS_SUCCESS != database_interface->handle_new(connection_options->database_interface_options, &database_interface_dbh)) {
599  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure! Can't create new handle! Can't connect to DSN %s\n", connection_options->database_interface_options.original_dsn);
600  goto end;
601  }
602 
603  if (database_interface_dbh) {
604  database_interface_dbh->connection_options = connection_options->database_interface_options;
605 
607  {
608  PROTECT_INTERFACE(database_interface)
609  switch_loadable_module_protect(database_interface->parent->module_name);
610  UNPROTECT_INTERFACE(database_interface)
611  }
612  }
613  }
614  break;
615  case SCDB_TYPE_ODBC:
616  {
617  if (!switch_odbc_available()) {
618  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure! ODBC NOT AVAILABLE! Can't connect to DSN %s\n", connection_options->odbc_options.dsn);
619  goto end;
620  }
621 
622  if ((odbc_dbh = switch_odbc_handle_new(connection_options->odbc_options.dsn,
623  connection_options->odbc_options.user, connection_options->odbc_options.pass))) {
625  switch_odbc_handle_destroy(&odbc_dbh);
626  }
627  }
628  }
629  break;
630  case SCDB_TYPE_CORE_DB:
631  {
632  if (!connection_options->core_db_options.in_memory) {
633  db = switch_core_db_open_file(connection_options->core_db_options.db_path);
634  } else {
635  db = switch_core_db_open_in_memory(connection_options->core_db_options.db_path);
636  }
637  }
638  break;
639 
640  default:
641  goto end;
642  }
643 
644  if (!db && !odbc_dbh && !database_interface_dbh) {
645  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure to connect to %s %s!\n", switch_cache_db_type_name(type), db_name);
646  goto end;
647  }
648 
649  new_dbh = create_handle(type);
650 
652  "Create Cached DB handle %s [%s] %s:%d\n", new_dbh->name, switch_cache_db_type_name(type), file, line);
653 
654  if (database_interface_dbh) {
655  new_dbh->native_handle.database_interface_dbh = database_interface_dbh;
656  } else if (db) {
657  if (!(new_dbh->native_handle.core_db_dbh = switch_core_alloc(new_dbh->pool, sizeof(*new_dbh->native_handle.core_db_dbh)))) {
658  destroy_handle(&new_dbh);
660  goto end;
661  }
662  new_dbh->native_handle.core_db_dbh->handle = db;
663  new_dbh->native_handle.core_db_dbh->in_memory = connection_options->core_db_options.in_memory;
664  } else if (odbc_dbh) {
665  new_dbh->native_handle.odbc_dbh = odbc_dbh;
666  }
667 
668  add_handle(new_dbh, db_str, db_callsite_str, thread_str);
669  }
670 
671  end:
672 
673  if (new_dbh) {
674  new_dbh->last_used = switch_epoch_time_now(NULL);
675  }
676 
677  *dbh = new_dbh;
678 
680 }
681 
682 
684 {
686  char *errmsg = NULL;
687  char *tmp = NULL;
688  char *type = NULL;
689 
690  if (err) {
691  *err = NULL;
692  }
693 
694  switch (dbh->type) {
696  {
699  status = database_interface_handle_exec(database_interface, dbh->native_handle.database_interface_dbh, sql, &errmsg);
700  }
701  break;
702  case SCDB_TYPE_ODBC:
703  {
704  type = "ODBC";
706  }
707  break;
708  case SCDB_TYPE_CORE_DB:
709  {
710  int ret = switch_core_db_exec(dbh->native_handle.core_db_dbh->handle, sql, NULL, NULL, &errmsg);
711  type = "NATIVE";
712 
713  if (ret == SWITCH_CORE_DB_OK) {
714  status = SWITCH_STATUS_SUCCESS;
715  }
716 
717  if (errmsg) {
718  switch_strdup(tmp, errmsg);
719  switch_core_db_free(errmsg);
720  errmsg = tmp;
721  }
722  }
723  break;
724  }
725 
726  if (errmsg) {
727  if (!switch_stristr("already exists", errmsg) && !switch_stristr("duplicate key name", errmsg)) {
728  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[%s] %s SQL ERR [%s]\n%s\n", dbh->name, (type ? type : "Unknown"), errmsg, sql);
729  }
730  if (err) {
731  *err = errmsg;
732  } else {
733  switch_safe_free(errmsg);
734  }
735  }
736 
737  return status;
738 }
739 
740 /**
741  OMFG you cruel bastards. Who chooses 64k as a max buffer len for a sql statement, have you ever heard of transactions?
742 **/
743 static switch_status_t switch_cache_db_execute_sql_chunked(switch_cache_db_handle_t *dbh, char *sql, uint32_t chunk_size, char **err)
744 {
746  char *p, *s, *e;
747  switch_size_t len;
748 
749  switch_assert(chunk_size);
750 
751  if (err)
752  *err = NULL;
753 
754  len = strlen(sql);
755 
756  if (chunk_size > len) {
757  return switch_cache_db_execute_sql_real(dbh, sql, err);
758  }
759 
760  if (!(strlen(sql) / chunk_size)) {
761  return SWITCH_STATUS_FALSE;
762  }
763 
764  e = end_of_p(sql);
765  s = sql;
766 
767  while (s && s < e) {
768  p = s + chunk_size;
769 
770  if (p > e) {
771  p = e;
772  }
773 
774  while (p > s) {
775  if (*p == '\n' && *(p - 1) == ';') {
776  *p = '\0';
777  *(p - 1) = '\0';
778  p++;
779  break;
780  }
781 
782  p--;
783  }
784 
785  status = switch_cache_db_execute_sql_real(dbh, s, err);
786  if (p <= s || status != SWITCH_STATUS_SUCCESS || (err && *err)) {
787  break;
788  }
789 
790  s = p;
791 
792  }
793 
794  return status;
795 
796 }
797 
798 
800 {
802 
803  switch (dbh->type) {
804  default:
805  {
806  status = switch_cache_db_execute_sql_chunked(dbh, (char *) sql, 32768, err);
807  }
808  break;
809  }
810 
811  return status;
812 }
813 
814 
816 {
817  switch (dbh->type) {
818  case SCDB_TYPE_CORE_DB:
819  {
821  }
822  break;
823  case SCDB_TYPE_ODBC:
824  {
826  }
827  break;
829  {
831  int affected_rows = 0;
832  database_interface->affected_rows(dbh->native_handle.database_interface_dbh, &affected_rows);
833  return affected_rows;
834  }
835  break;
836  }
837  return 0;
838 }
839 
841 {
842  switch (dbh->type) {
843  case SCDB_TYPE_CORE_DB:
844  {
845  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "try to load extension [%s]!\n", extension);
847  }
848  break;
849  case SCDB_TYPE_ODBC:
850  {
851  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "load extension not supported by type ODBC!\n");
852  }
853  break;
855  {
856  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "load extension not supported by type DATABASE_INTERFACE!\n");
857  }
858  break;
859  }
860  return 0;
861 }
862 
863 
864 SWITCH_DECLARE(char *) switch_cache_db_execute_sql2str(switch_cache_db_handle_t *dbh, char *sql, char *str, size_t len, char **err)
865 {
867 
868  memset(str, 0, len);
869 
870  switch (dbh->type) {
871  case SCDB_TYPE_CORE_DB:
872  {
873  switch_core_db_stmt_t *stmt;
874 
875  if (switch_core_db_prepare(dbh->native_handle.core_db_dbh->handle, sql, -1, &stmt, 0)) {
876  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Statement Error [%s]!\n", sql);
877  goto end;
878  } else {
879  int running = 1;
880 
881  while (running < 5000) {
882  int result = switch_core_db_step(stmt);
883  const unsigned char *txt;
884 
885  if (result == SWITCH_CORE_DB_ROW) {
886  if (switch_core_db_column_count(stmt) > 0) {
887  if ((txt = switch_core_db_column_text(stmt, 0))) {
888  switch_copy_string(str, (char *) txt, len);
889  status = SWITCH_STATUS_SUCCESS;
890  }
891  }
892  break;
893  } else if (result == SWITCH_CORE_DB_BUSY) {
894  running++;
896  continue;
897  }
898  break;
899  }
900 
902  }
903  }
904  break;
905  case SCDB_TYPE_ODBC:
906  {
908  }
909  break;
911  {
913  status = database_interface->exec_string(dbh->native_handle.database_interface_dbh, sql, str, len, err);
914  }
915  break;
916  }
917 
918  end:
919 
920  return status == SWITCH_STATUS_SUCCESS ? str : NULL;
921 
922 }
923 
925 {
926  char *errmsg = NULL;
928  uint8_t forever = 0;
929 
930  if (!retries) {
931  forever = 1;
932  retries = 1000;
933  }
934 
935  while (retries > 0) {
936 
937  switch_cache_db_execute_sql_real(dbh, sql, &errmsg);
938 
939  if (errmsg) {
940  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s]\n", errmsg);
941  switch_safe_free(errmsg);
942  switch_yield(100000);
943  retries--;
944  if (retries == 0 && forever) {
945  retries = 1000;
946  continue;
947  }
948  } else {
949  status = SWITCH_STATUS_SUCCESS;
950  break;
951  }
952  }
953 
954  return status;
955 }
956 
957 
959  char *sql, uint32_t retries,
960  const char *pre_trans_execute,
961  const char *post_trans_execute,
962  const char *inner_pre_trans_execute,
963  const char *inner_post_trans_execute)
964 {
965  char *errmsg = NULL;
967  uint8_t forever = 0;
968  unsigned begin_retries = 100;
969  uint8_t again = 0;
970 
971  if (!retries) {
972  forever = 1;
973  retries = 1000;
974  }
975 
976  if (!zstr(pre_trans_execute)) {
977  switch_cache_db_execute_sql_real(dbh, pre_trans_execute, &errmsg);
978  if (errmsg) {
979  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL PRE TRANS EXEC %s [%s]\n", pre_trans_execute, errmsg);
980  switch_safe_free(errmsg);
981  }
982  }
983 
984  again:
985 
986  while (begin_retries > 0) {
987  again = 0;
988 
989  switch(dbh->type) {
990  case SCDB_TYPE_CORE_DB:
991  {
992  switch_cache_db_execute_sql_real(dbh, "BEGIN EXCLUSIVE", &errmsg);
993  }
994  break;
995  case SCDB_TYPE_ODBC:
996  {
997  switch_odbc_status_t result;
998 
1000  char tmp[100];
1001  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to Set AutoCommit Off", result);
1002  errmsg = strdup(tmp);
1003  }
1004  }
1005  break;
1007  {
1009  switch_status_t result;
1010 
1011  if ((result = database_interface->sql_set_auto_commit_attr(dbh->native_handle.database_interface_dbh, 0)) != SWITCH_STATUS_SUCCESS) {
1012  char tmp[100];
1013  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to Set AutoCommit Off", result);
1014  errmsg = strdup(tmp);
1015  }
1016  }
1017  break;
1018  }
1019 
1020  if (errmsg) {
1021  begin_retries--;
1022  if (strstr(errmsg, "cannot start a transaction within a transaction")) {
1023  again = 1;
1024  } else {
1025  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL Retry [%s]\n", errmsg);
1026  }
1027  switch_safe_free(errmsg);
1028 
1029  if (again) {
1030  switch(dbh->type) {
1031  case SCDB_TYPE_CORE_DB:
1032  {
1033  switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL);
1034  }
1035  break;
1036  case SCDB_TYPE_ODBC:
1037  {
1040  }
1041  break;
1043  {
1045  switch_status_t result;
1046 
1047  if ((result = database_interface->commit(dbh->native_handle.database_interface_dbh)) != SWITCH_STATUS_SUCCESS) {
1048  char tmp[100];
1049  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to commit transaction", result);
1050  }
1051  }
1052  break;
1053  }
1054 
1055  goto again;
1056  }
1057 
1058  switch_yield(100000);
1059 
1060  if (begin_retries == 0) {
1061  goto done;
1062  }
1063 
1064  continue;
1065  }
1066 
1067  break;
1068  }
1069 
1070 
1071  if (!zstr(inner_pre_trans_execute)) {
1072  switch_cache_db_execute_sql_real(dbh, inner_pre_trans_execute, &errmsg);
1073  if (errmsg) {
1074  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL PRE TRANS EXEC %s [%s]\n", inner_pre_trans_execute, errmsg);
1075  switch_safe_free(errmsg);
1076  }
1077  }
1078 
1079  while (retries > 0) {
1080 
1081  switch_cache_db_execute_sql(dbh, sql, &errmsg);
1082 
1083  if (errmsg) {
1084  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s]\n", errmsg);
1085  switch_safe_free(errmsg);
1086  errmsg = NULL;
1087  switch_yield(100000);
1088  retries--;
1089  if (retries == 0 && forever) {
1090  retries = 1000;
1091  continue;
1092  }
1093  } else {
1094  status = SWITCH_STATUS_SUCCESS;
1095  break;
1096  }
1097  }
1098 
1099  if (!zstr(inner_post_trans_execute)) {
1100  switch_cache_db_execute_sql_real(dbh, inner_post_trans_execute, &errmsg);
1101  if (errmsg) {
1102  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL POST TRANS EXEC %s [%s]\n", inner_post_trans_execute, errmsg);
1103  switch_safe_free(errmsg);
1104  }
1105  }
1106 
1107  done:
1108 
1109  switch(dbh->type) {
1110  case SCDB_TYPE_CORE_DB:
1111  {
1112  switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL);
1113  }
1114  break;
1115  case SCDB_TYPE_ODBC:
1116  {
1119  }
1120  break;
1122  {
1124  switch_status_t result;
1125 
1126  if ((result = database_interface->commit(dbh->native_handle.database_interface_dbh)) != SWITCH_STATUS_SUCCESS) {
1127  char tmp[100];
1128  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to commit transaction", result);
1129  }
1130  }
1131  break;
1132  }
1133 
1134  if (!zstr(post_trans_execute)) {
1135  switch_cache_db_execute_sql_real(dbh, post_trans_execute, &errmsg);
1136  if (errmsg) {
1137  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL POST TRANS EXEC %s [%s]\n", post_trans_execute, errmsg);
1138  switch_safe_free(errmsg);
1139  }
1140  }
1141 
1142  return status;
1143 }
1144 
1145 struct helper {
1147  void *pdata;
1148 };
1149 
1150 static int helper_callback(void *pArg, int argc, char **argv, char **columnNames)
1151 {
1152  struct helper *h = (struct helper *) pArg;
1153  int r = 0;
1154  switch_event_t *event;
1155 
1156  switch_event_create_array_pair(&event, columnNames, argv, argc);
1157 
1158  r = h->callback(h->pdata, event);
1159 
1160  switch_event_destroy(&event);
1161 
1162  return r;
1163 }
1164 
1166  const char *sql, switch_core_db_event_callback_func_t callback, void *pdata, char **err)
1167 {
1169  char *errmsg = NULL;
1170  struct helper h = {0};
1171 
1172  if (err) {
1173  *err = NULL;
1174  }
1175 
1176  h.callback = callback;
1177  h.pdata = pdata;
1178 
1179  switch (dbh->type) {
1181  {
1183 
1184  if ((status = database_interface_handle_callback_exec(database_interface, dbh->native_handle.database_interface_dbh, sql, helper_callback, &h, err)) != SWITCH_STATUS_SUCCESS) {
1185  char tmp[100];
1186  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to execute_sql_event_callback", status);
1187  }
1188  }
1189  break;
1190  case SCDB_TYPE_ODBC:
1191  {
1193  }
1194  break;
1195  case SCDB_TYPE_CORE_DB:
1196  {
1197  int ret = switch_core_db_exec(dbh->native_handle.core_db_dbh->handle, sql, helper_callback, &h, &errmsg);
1198 
1199  if (ret == SWITCH_CORE_DB_OK || ret == SWITCH_CORE_DB_ABORT) {
1200  status = SWITCH_STATUS_SUCCESS;
1201  }
1202 
1203  if (errmsg) {
1204  dbh->last_used = switch_epoch_time_now(NULL) - (SQL_CACHE_TIMEOUT * 2);
1205  if (!strstr(errmsg, "query abort")) {
1206  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: [%s] %s\n", sql, errmsg);
1207  }
1208  switch_core_db_free(errmsg);
1209  }
1210  }
1211  break;
1212  }
1213 
1214  return status;
1215 }
1216 
1220  void *pdata, char **err)
1221 {
1223  char *errmsg = NULL;
1224  struct helper h;
1225 
1226 
1227  if (err) {
1228  *err = NULL;
1229  }
1230 
1231  h.callback = callback;
1232  h.pdata = pdata;
1233 
1234  switch (dbh->type) {
1236  {
1238 
1239  if ((status = database_interface_handle_callback_exec(database_interface, dbh->native_handle.database_interface_dbh, sql, helper_callback, &h, err)) != SWITCH_STATUS_SUCCESS) {
1240  char tmp[100];
1241  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to execute_sql_event_callback_err", status);
1242  }
1243 
1244  if (err && *err) {
1245  (*err_callback)(pdata, (const char*)*err);
1246  }
1247  }
1248  break;
1249  case SCDB_TYPE_ODBC:
1250  {
1252  if (err && *err) {
1253  (*err_callback)(pdata, (const char*)*err);
1254  }
1255  }
1256  break;
1257  case SCDB_TYPE_CORE_DB:
1258  {
1259  int ret = switch_core_db_exec(dbh->native_handle.core_db_dbh->handle, sql, helper_callback, &h, &errmsg);
1260 
1261  if (ret == SWITCH_CORE_DB_OK || ret == SWITCH_CORE_DB_ABORT) {
1262  status = SWITCH_STATUS_SUCCESS;
1263  }
1264 
1265  if (errmsg) {
1266  dbh->last_used = switch_epoch_time_now(NULL) - (SQL_CACHE_TIMEOUT * 2);
1267  if (!strstr(errmsg, "query abort")) {
1268  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: [%s] %s\n", sql, errmsg);
1269  }
1270  }
1271  if ((ret == SWITCH_CORE_DB_ABORT || errmsg) && err_callback) {
1272  (*err_callback)(pdata, errmsg);
1273  }
1274  if (errmsg) {
1275  switch_core_db_free(errmsg);
1276  }
1277  }
1278  break;
1279  }
1280 
1281 
1282  return status;
1283 }
1284 
1286  const char *sql, switch_core_db_callback_func_t callback, void *pdata, char **err)
1287 {
1289  char *errmsg = NULL;
1290 
1291  if (err) {
1292  *err = NULL;
1293  }
1294 
1295  switch (dbh->type) {
1297  {
1299 
1300  if ((status = database_interface_handle_callback_exec(database_interface, dbh->native_handle.database_interface_dbh, sql, callback, pdata, err)) != SWITCH_STATUS_SUCCESS) {
1301  char tmp[100];
1302  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to execute_sql_callback", status);
1303  }
1304  }
1305  break;
1306  case SCDB_TYPE_ODBC:
1307  {
1309  }
1310  break;
1311  case SCDB_TYPE_CORE_DB:
1312  {
1313  int ret = switch_core_db_exec(dbh->native_handle.core_db_dbh->handle, sql, callback, pdata, &errmsg);
1314 
1315  if (ret == SWITCH_CORE_DB_OK || ret == SWITCH_CORE_DB_ABORT) {
1316  status = SWITCH_STATUS_SUCCESS;
1317  }
1318 
1319  if (errmsg) {
1320  dbh->last_used = switch_epoch_time_now(NULL) - (SQL_CACHE_TIMEOUT * 2);
1321  if (!strstr(errmsg, "query abort")) {
1322  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: [%s] %s\n", sql, errmsg);
1323  }
1324  switch_core_db_free(errmsg);
1325  }
1326  }
1327  break;
1328  }
1329 
1330  return status;
1331 }
1332 
1335  switch_core_db_err_callback_func_t err_callback, void *pdata, char **err)
1336 {
1338  char *errmsg = NULL;
1339 
1340  if (err) {
1341  *err = NULL;
1342  }
1343 
1344  switch (dbh->type) {
1346  {
1348 
1349  if ((status = database_interface_handle_callback_exec(database_interface, dbh->native_handle.database_interface_dbh, sql, callback, pdata, err)) != SWITCH_STATUS_SUCCESS) {
1350  char tmp[100];
1351  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to execute_sql_callback_err", status);
1352  }
1353 
1354  if (err && *err) {
1355  (*err_callback)(pdata, (const char*)*err);
1356  }
1357  }
1358  break;
1359  case SCDB_TYPE_ODBC:
1360  {
1362  if (err && *err) {
1363  (*err_callback)(pdata, (const char*)*err);
1364  }
1365  }
1366  break;
1367  case SCDB_TYPE_CORE_DB:
1368  {
1369  int ret = switch_core_db_exec(dbh->native_handle.core_db_dbh->handle, sql, callback, pdata, &errmsg);
1370 
1371  if (ret == SWITCH_CORE_DB_OK || ret == SWITCH_CORE_DB_ABORT) {
1372  status = SWITCH_STATUS_SUCCESS;
1373  }
1374 
1375  if (errmsg) {
1376  dbh->last_used = switch_epoch_time_now(NULL) - (SQL_CACHE_TIMEOUT * 2);
1377  if (!strstr(errmsg, "query abort")) {
1378  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: [%s] %s\n", sql, errmsg);
1379  }
1380  }
1381  if ((ret == SWITCH_CORE_DB_ABORT || errmsg) && err_callback) {
1382  (*err_callback)(pdata, errmsg);
1383  }
1384  if (errmsg) {
1385  switch_core_db_free(errmsg);
1386  }
1387  }
1388  break;
1389  }
1390 
1391  return status;
1392 }
1393 
1395 {
1397 
1398  switch_assert(sql != NULL);
1399 
1401  r = switch_cache_db_execute_sql(dbh, sql, err);
1402  }
1403 
1404  return r;
1405 }
1406 
1407 /*!
1408  * \brief Performs test_sql and if it fails performs drop_sql and reactive_sql.
1409  *
1410  * If auto-clear-sql is disabled, then this function will do nothing and it is
1411  * assumed that the queries are not needed. If auto-create-schemas is disabled,
1412  * then just test_sql is executed, but drop_sql and reactive_sql are not.
1413  *
1414  * Otherwise, test_sql gets executed. If that succeeds, then there is nothing to
1415  * do. Otherwise drop_sql is executed (its result is ignored) and then finally
1416  * reactive_sql is executed.
1417  *
1418  * \return If auto-create-schemas is enabled, SWITCH_TRUE is returned if
1419  * test_sql succeeds, SWITCH_FALSE otherwise. If reactive_sql is executed
1420  * successfully SWITCH_TRUE is returned, otherwise SWITCH_FALSE is returned.
1421  */
1423  const char *test_sql, const char *drop_sql, const char *reactive_sql)
1424 {
1425  return switch_cache_db_test_reactive_ex(dbh, test_sql, drop_sql, reactive_sql, NULL);
1426 }
1427 
1429  const char *test_sql, const char *drop_sql, const char *reactive_sql, const char *row_size_limited_reactive_sql)
1430 {
1432 
1433  switch_assert(test_sql != NULL);
1434  switch_assert(reactive_sql != NULL);
1435 
1437  return SWITCH_TRUE;
1438  }
1439 
1441  switch_status_t status = switch_cache_db_execute_sql(dbh, (char *)test_sql, NULL);
1442 
1443  return (status == SWITCH_STATUS_SUCCESS) ? SWITCH_TRUE : SWITCH_FALSE;
1444  }
1445 
1446  switch (dbh->type) {
1448  {
1450  switch_status_t result;
1451 
1452  if ((result = database_interface_handle_exec(database_interface, dbh->native_handle.database_interface_dbh, test_sql, NULL)) != SWITCH_STATUS_SUCCESS) {
1453  char tmp[100];
1454  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to test_reactive with test_sql", result);
1455 
1456  if (drop_sql) {
1457  if ((result = database_interface_handle_exec(database_interface, dbh->native_handle.database_interface_dbh, drop_sql, NULL)) != SWITCH_STATUS_SUCCESS) {
1458  char tmp[100];
1459  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to test_reactive with drop_sql", result);
1460  }
1461  }
1462 
1463  if ((result = database_interface_handle_exec(database_interface, dbh->native_handle.database_interface_dbh, reactive_sql, NULL)) != SWITCH_STATUS_SUCCESS) {
1464  char tmp[100];
1465  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to test_reactive with reactive_sql", result);
1466 
1467  if (row_size_limited_reactive_sql && switch_test_flag(database_interface, SWITCH_DATABASE_FLAG_ROW_SIZE_LIMIT)) {
1468  if ((result = database_interface_handle_exec(database_interface, dbh->native_handle.database_interface_dbh, row_size_limited_reactive_sql, NULL)) != SWITCH_STATUS_SUCCESS) {
1469  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to test_reactive with row_size_limited_reactive_sql", result);
1470  }
1471  }
1472  }
1473 
1474  r = (result == SWITCH_STATUS_SUCCESS);
1475  }
1476  }
1477  break;
1478  case SCDB_TYPE_ODBC:
1479  {
1480  if (switch_odbc_handle_exec(dbh->native_handle.odbc_dbh, test_sql, NULL, NULL) != SWITCH_ODBC_SUCCESS) {
1481  if (drop_sql) {
1482  switch_odbc_handle_exec(dbh->native_handle.odbc_dbh, drop_sql, NULL, NULL);
1483  }
1484  r = switch_odbc_handle_exec(dbh->native_handle.odbc_dbh, reactive_sql, NULL, NULL) == SWITCH_ODBC_SUCCESS;
1485  }
1486  }
1487  break;
1488  case SCDB_TYPE_CORE_DB:
1489  {
1490  char *errmsg = NULL;
1491  switch_core_db_exec(dbh->native_handle.core_db_dbh->handle, test_sql, NULL, NULL, &errmsg);
1492 
1493  if (errmsg) {
1494  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL ERR [%s]\n[%s]\nAuto Generating Table!\n", errmsg, test_sql);
1495  switch_core_db_free(errmsg);
1496  errmsg = NULL;
1497  if (drop_sql) {
1498  switch_core_db_exec(dbh->native_handle.core_db_dbh->handle, drop_sql, NULL, NULL, &errmsg);
1499  }
1500  if (errmsg) {
1501  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Ignoring SQL ERR [%s]\n[%s]\n", errmsg, drop_sql);
1502  switch_core_db_free(errmsg);
1503  errmsg = NULL;
1504  }
1505  switch_core_db_exec(dbh->native_handle.core_db_dbh->handle, reactive_sql, NULL, NULL, &errmsg);
1506  if (errmsg) {
1507  r = SWITCH_FALSE;
1508  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL ERR [%s]\n[%s]\n", errmsg, reactive_sql);
1509  switch_core_db_free(errmsg);
1510  errmsg = NULL;
1511  } else {
1512  r = SWITCH_TRUE;
1513  }
1514  }
1515  }
1516  break;
1517  }
1518 
1519  return r;
1520 }
1521 
1522 
1524 {
1525  int sec = 0, reg_sec = 0;;
1526 
1527  sql_manager.db_thread_running = 1;
1528 
1529  while (sql_manager.db_thread_running == 1) {
1530  if (++sec == SQL_CACHE_TIMEOUT) {
1532  sec = 0;
1533  }
1534 
1535  if (switch_test_flag((&runtime), SCF_USE_SQL) && ++reg_sec == SQL_REG_TIMEOUT) {
1537  reg_sec = 0;
1538  }
1539  switch_yield(1000000);
1540  }
1541 
1542 
1543  return NULL;
1544 }
1545 
1546 
1548 
1550  const char *name;
1553  uint32_t *pre_written;
1554  uint32_t *written;
1555  uint32_t numq;
1556  char *dsn;
1569  uint32_t max_trans;
1570  uint32_t confirm;
1571  uint8_t paused;
1573 };
1574 
1576 {
1577  switch_status_t status;
1578  int tries = 0;
1579 
1580  top:
1581 
1582  status = switch_mutex_trylock(qm->cond_mutex);
1583 
1584  if (status == SWITCH_STATUS_SUCCESS) {
1587  return 1;
1588  } else {
1590  qm->skip_wait++;
1592  } else {
1593  if (++tries < 10) {
1594  switch_cond_next();
1595  goto top;
1596  }
1597  }
1598  }
1599 
1600  return 0;
1601 }
1602 
1604 {
1605  uint32_t ttl = 0;
1606  uint32_t i;
1607 
1608  for (i = 0; i < qm->numq; i++) {
1609  ttl += switch_queue_size(qm->sql_queue[i]);
1610  }
1611 
1612  return ttl;
1613 }
1614 
1615 struct db_job {
1617  char *sql;
1622  void *pdata;
1623  int event;
1625 };
1626 
1628 {
1629  struct db_job *job = (struct db_job *) obj;
1630  switch_memory_pool_t *pool = job->pool;
1631  char *err = NULL;
1633 
1634 
1636  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot connect DSN %s\n", job->qm->dsn);
1637  return NULL;
1638  }
1639 
1640  if (job->callback && !job->err_callback) {
1641  switch_cache_db_execute_sql_callback(dbh, job->sql, job->callback, job->pdata, &err);
1642  } else if (job->callback && job->err_callback) {
1643  switch_cache_db_execute_sql_callback_err(dbh, job->sql, job->callback, job->err_callback, job->pdata, &err);
1644  } else if (job->event_callback && !job->event_err_callback) {
1646  } else if (job->event_callback && job->event_err_callback) {
1648  }
1649 
1650  if (err) {
1651  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: [%s] %s\n", job->sql, err);
1652  switch_safe_free(err);
1653  }
1654 
1656 
1657  if (pool) {
1659  }
1660 
1661  return NULL;
1662 }
1663 
1669  void *pdata)
1670 {
1673  struct db_job *job;
1675 
1676  td = switch_core_alloc(pool, sizeof(*td));
1677  job = switch_core_alloc(pool, sizeof(*job));
1678 
1679  td->func = sql_in_thread;
1680  td->obj = job;
1681 
1682  job->sql = switch_core_strdup(pool, sql);
1683  job->qm = qm;
1684 
1685  if (callback) {
1686  job->callback = callback;
1687  job->err_callback = err_callback;
1688  } else if (event_callback) {
1691  }
1692 
1693  job->pdata = pdata;
1694  job->pool = pool;
1695 
1696  return td;
1697 }
1698 
1699 
1701  const char *sql, switch_core_db_callback_func_t callback, void *pdata)
1702 {
1703 
1705  if ((td = new_job(qm, sql, callback, NULL, NULL, NULL, pdata))) {
1707  }
1708 }
1709 
1713 {
1714 
1716  if ((td = new_job(qm, sql, callback, err_callback, NULL, NULL, pdata))) {
1718  }
1719 }
1720 
1723 {
1724 
1726  if ((td = new_job(qm, sql, NULL, NULL, callback, NULL, pdata))) {
1728  }
1729 }
1730 
1734  void *pdata)
1735 {
1736 
1738  if ((td = new_job(qm, sql, NULL, NULL, callback, err_callback, pdata))) {
1740  }
1741 }
1742 
1743 
1745 {
1746  void *pop = NULL;
1747  switch_queue_t *q = qm->sql_queue[i];
1748 
1749  switch_mutex_lock(qm->mutex);
1750  while (switch_queue_trypop(q, &pop) == SWITCH_STATUS_SUCCESS) {
1751  if (pop) {
1752  if (dbh) {
1753  switch_cache_db_execute_sql(dbh, (char *) pop, NULL);
1754  }
1755  switch_safe_free(pop);
1756  }
1757  }
1759 
1760 }
1761 
1762 
1764 {
1765  switch_mutex_lock(qm->mutex);
1766  qm->paused = 0;
1768 
1769  qm_wake(qm);
1770 
1771 }
1772 
1774 {
1775  uint32_t i;
1776 
1777  switch_mutex_lock(qm->mutex);
1778  qm->paused = 1;
1780 
1781  if (flush) {
1782  for(i = 0; i < qm->numq; i++) {
1783  do_flush(qm, i, NULL);
1784  }
1785  }
1786 
1787 }
1788 
1790 {
1791  int size = 0;
1792 
1793  switch_mutex_lock(qm->mutex);
1794  if (index < qm->numq) {
1795  size = switch_queue_size(qm->sql_queue[index]);
1796  }
1798 
1799  return size;
1800 }
1801 
1803 {
1805  uint32_t i, sanity = 100;
1806 
1807  if (qm->thread_running == 1) {
1808  qm->thread_running = -1;
1809 
1810  while(--sanity && qm->thread_running == -1) {
1811  for(i = 0; i < qm->numq; i++) {
1812  switch_queue_push(qm->sql_queue[i], NULL);
1814  }
1815  qm_wake(qm);
1816 
1817  if (qm->thread_running == -1) {
1818  switch_yield(100000);
1819  }
1820  }
1821  status = SWITCH_STATUS_SUCCESS;
1822  }
1823 
1824  if (qm->thread) {
1825  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Stopping SQL thread.\n", qm->name);
1826  qm_wake(qm);
1827  switch_thread_join(&status, qm->thread);
1828  qm->thread = NULL;
1829  status = SWITCH_STATUS_SUCCESS;
1830  }
1831 
1832  return status;
1833 }
1834 
1836 {
1837  switch_threadattr_t *thd_attr;
1838 
1839  if (!qm->thread_running) {
1840  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Starting SQL thread.\n", qm->name);
1841  switch_threadattr_create(&thd_attr, qm->pool);
1845  while (!qm->thread_initiated) {
1846  switch_cond_next();
1847  }
1848 
1849  if (qm->event_db) {
1850  return SWITCH_STATUS_SUCCESS;
1851  }
1852  }
1853  }
1854 
1855  return SWITCH_STATUS_FALSE;
1856 }
1857 
1859 {
1863  uint32_t i;
1864 
1865  switch_assert(qmp);
1866  qm = *qmp;
1867  if (!qm) {
1868  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No SQL queue to destroy.\n");
1869  return SWITCH_STATUS_NOOP;
1870  }
1871 
1872  *qmp = NULL;
1873 
1874  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Destroying SQL queue.\n", qm->name);
1875 
1877 
1878 
1879 
1880  for(i = 0; i < qm->numq; i++) {
1881  do_flush(qm, i, NULL);
1882  }
1883 
1884  pool = qm->pool;
1886 
1887  return status;
1888 }
1889 
1891 {
1892  char *sqlptr = NULL;
1893  switch_status_t status;
1894  int x = 0;
1895 
1896  if (sql_manager.paused || qm->thread_running != 1) {
1898  if (!dup) free((char *)sql);
1899  qm_wake(qm);
1900  return SWITCH_STATUS_SUCCESS;
1901  }
1902 
1903  if (qm->thread_running != 1) {
1904  if (!dup) free((char *)sql);
1905  return SWITCH_STATUS_FALSE;
1906  }
1907 
1908  if (pos > qm->numq - 1) {
1909  pos = 0;
1910  }
1911 
1912  sqlptr = dup ? strdup(sql) : (char *)sql;
1913 
1914  do {
1915  switch_mutex_lock(qm->mutex);
1916  status = switch_queue_trypush(qm->sql_queue[pos], sqlptr);
1918  if (status != SWITCH_STATUS_SUCCESS) {
1919  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Delay %d sending sql\n", x);
1920  if (x++) {
1921  switch_yield(1000000 * x);
1922  }
1923  }
1924  } while(status != SWITCH_STATUS_SUCCESS);
1925 
1926  qm_wake(qm);
1927 
1928  return SWITCH_STATUS_SUCCESS;
1929 }
1930 
1931 
1933 {
1934 #define EXEC_NOW
1935 #ifdef EXEC_NOW
1937 
1938  if (sql_manager.paused || qm->thread_running != 1) {
1940  if (!dup) free((char *)sql);
1941  qm_wake(qm);
1942  return SWITCH_STATUS_SUCCESS;
1943  }
1944 
1946  switch_cache_db_execute_sql(dbh, (char *)sql, NULL);
1948  }
1949 
1950  if (!dup) free((char *)sql);
1951 
1952 #else
1953 
1954  int size, x = 0, sanity = 0;
1955  uint32_t written, want;
1956 
1957  if (sql_manager.paused) {
1958  if (!dup) free((char *)sql);
1959  qm_wake(qm);
1960  return SWITCH_STATUS_SUCCESS;
1961  }
1962 
1963  if (qm->thread_running != 1) {
1964  if (!dup) free((char *)sql);
1965  return SWITCH_STATUS_FALSE;
1966  }
1967 
1968  if (pos > qm->numq - 1) {
1969  pos = 0;
1970  }
1971 
1972  switch_mutex_lock(qm->mutex);
1973  qm->confirm++;
1974  switch_queue_push(qm->sql_queue[pos], dup ? strdup(sql) : (char *)sql);
1975  written = qm->pre_written[pos];
1976  size = switch_sql_queue_manager_size(qm, pos);
1977  want = written + size;
1979 
1980  qm_wake(qm);
1981 
1982  while((qm->written[pos] < want) || (qm->written[pos] >= written && want < written && qm->written[pos] > want)) {
1983  switch_yield(5000);
1984 
1985  if (++x == 200) {
1986  qm_wake(qm);
1987  x = 0;
1988  if (++sanity == 20) {
1989  break;
1990  }
1991  }
1992  }
1993 
1994  switch_mutex_lock(qm->mutex);
1995  qm->confirm--;
1997 #endif
1998 
1999  return SWITCH_STATUS_SUCCESS;
2000 }
2001 
2002 
2003 
2004 
2005 
2008  uint32_t numq, const char *dsn, uint32_t max_trans,
2009  const char *pre_trans_execute,
2010  const char *post_trans_execute,
2011  const char *inner_pre_trans_execute,
2012  const char *inner_post_trans_execute)
2013 {
2016  uint32_t i;
2017 
2018  if (!numq) numq = 1;
2019 
2021  qm = switch_core_alloc(pool, sizeof(*qm));
2022 
2023  qm->pool = pool;
2024  qm->numq = numq;
2025  qm->dsn = switch_core_strdup(qm->pool, dsn);
2026  qm->name = switch_core_strdup(qm->pool, name);
2027  qm->max_trans = max_trans;
2028 
2032  switch_thread_cond_create(&qm->cond, qm->pool);
2033 
2034  qm->sql_queue = switch_core_alloc(qm->pool, sizeof(switch_queue_t *) * numq);
2035  qm->written = switch_core_alloc(qm->pool, sizeof(uint32_t) * numq);
2036  qm->pre_written = switch_core_alloc(qm->pool, sizeof(uint32_t) * numq);
2037 
2038  for (i = 0; i < qm->numq; i++) {
2040  }
2041 
2042  if (pre_trans_execute) {
2043  qm->pre_trans_execute = switch_core_strdup(qm->pool, pre_trans_execute);
2044  }
2045  if (post_trans_execute) {
2046  qm->post_trans_execute = switch_core_strdup(qm->pool, post_trans_execute);
2047  }
2048  if (inner_pre_trans_execute) {
2049  qm->inner_pre_trans_execute = switch_core_strdup(qm->pool, inner_pre_trans_execute);
2050  }
2051  if (inner_post_trans_execute) {
2052  qm->inner_post_trans_execute = switch_core_strdup(qm->pool, inner_post_trans_execute);
2053  }
2054 
2055  *qmp = qm;
2056 
2057  return SWITCH_STATUS_SUCCESS;
2058 
2059 }
2060 
2062 {
2063  char *errmsg = NULL;
2064  void *pop;
2065  switch_status_t status;
2066  uint32_t ttl = 0;
2067  uint32_t i;
2068  switch_status_t res;
2069 
2070  if (!zstr(qm->pre_trans_execute)) {
2072  if (errmsg) {
2073  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL PRE TRANS EXEC %s [%s]\n", qm->pre_trans_execute, errmsg);
2074  switch_safe_free(errmsg);
2075  }
2076  }
2077 
2078  switch(qm->event_db->type) {
2079  case SCDB_TYPE_CORE_DB:
2080  {
2081  switch_cache_db_execute_sql_real(qm->event_db, "BEGIN EXCLUSIVE", &errmsg);
2082  }
2083  break;
2084  case SCDB_TYPE_ODBC:
2085  {
2086  switch_odbc_status_t result;
2087 
2089  char tmp[100];
2090  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to Set AutoCommit Off", result);
2091  errmsg = strdup(tmp);
2092  }
2093  }
2094  break;
2096  {
2098  switch_status_t result;
2099 
2100  if ((result = database_interface->sql_set_auto_commit_attr(qm->event_db->native_handle.database_interface_dbh, 0)) != SWITCH_STATUS_SUCCESS) {
2101  char tmp[100];
2102  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to Set AutoCommit Off", result);
2103  errmsg = strdup(tmp);
2104  }
2105  }
2106  break;
2107  }
2108 
2109  if (errmsg) {
2110  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "ERROR [%s], [%s]\n", errmsg, qm->event_db->name);
2111  switch_safe_free(errmsg);
2112  goto end;
2113  }
2114 
2115 
2116  if (!zstr(qm->inner_pre_trans_execute)) {
2118  if (errmsg) {
2119  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL PRE TRANS EXEC %s [%s]\n", qm->inner_pre_trans_execute, errmsg);
2120  switch_safe_free(errmsg);
2121  }
2122  }
2123 
2124 
2125  while(qm->max_trans == 0 || ttl <= qm->max_trans) {
2126  pop = NULL;
2127 
2128  for (i = 0; (qm->max_trans == 0 || ttl <= qm->max_trans) && (i < qm->numq); i++) {
2129  switch_mutex_lock(qm->mutex);
2130  res = switch_queue_trypop(qm->sql_queue[i], &pop);
2131  (void)res;
2133  if (pop) break;
2134  }
2135 
2136  if (pop) {
2137  if ((status = switch_cache_db_execute_sql(qm->event_db, (char *) pop, NULL)) == SWITCH_STATUS_SUCCESS) {
2138  switch_mutex_lock(qm->mutex);
2139  qm->pre_written[i]++;
2141  ttl++;
2142  }
2143 
2144  switch_safe_free(pop);
2145  if (status != SWITCH_STATUS_SUCCESS) break;
2146  } else {
2147  break;
2148  }
2149  }
2150 
2151  if (!zstr(qm->inner_post_trans_execute)) {
2153  if (errmsg) {
2154  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL POST TRANS EXEC %s [%s]\n", qm->inner_post_trans_execute, errmsg);
2155  switch_safe_free(errmsg);
2156  }
2157  }
2158 
2159  end:
2160 
2161  switch(qm->event_db->type) {
2162  case SCDB_TYPE_CORE_DB:
2163  {
2164  switch_cache_db_execute_sql_real(qm->event_db, "COMMIT", NULL);
2165  }
2166  break;
2167  case SCDB_TYPE_ODBC:
2168  {
2171  }
2172  break;
2174  {
2176  switch_status_t result;
2177 
2178  if ((result = database_interface->commit(qm->event_db->native_handle.database_interface_dbh)) != SWITCH_STATUS_SUCCESS) {
2179  char tmp[100];
2180  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to commit transaction", result);
2181  }
2182  }
2183  break;
2184  }
2185 
2186 
2187  if (!zstr(qm->post_trans_execute)) {
2189  if (errmsg) {
2190  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL POST TRANS EXEC %s [%s]\n", qm->post_trans_execute, errmsg);
2191  switch_safe_free(errmsg);
2192  }
2193  }
2194 
2195  switch_mutex_lock(qm->mutex);
2196  for (i = 0; i < qm->numq; i++) {
2197  qm->written[i] = qm->pre_written[i];
2198  }
2199 
2201 
2202  return ttl;
2203 }
2204 
2206 {
2207 
2208  uint32_t sanity = 120;
2210  uint32_t i;
2211 
2212  while (sanity && !qm->event_db) {
2214  break;
2215  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s Error getting db handle, Retrying\n", qm->name);
2216  switch_yield(500000);
2217  sanity--;
2218  }
2219 
2220  if (!qm->event_db) {
2221  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%s Error getting db handle\n", qm->name);
2222  qm->thread_initiated = 1;
2223  return NULL;
2224  }
2225 
2227 
2228  switch (qm->event_db->type) {
2230  break;
2231  case SCDB_TYPE_ODBC:
2232  break;
2233  case SCDB_TYPE_CORE_DB:
2234  {
2235  switch_cache_db_execute_sql(qm->event_db, "PRAGMA synchronous=OFF;", NULL);
2236  switch_cache_db_execute_sql(qm->event_db, "PRAGMA count_changes=OFF;", NULL);
2237  switch_cache_db_execute_sql(qm->event_db, "PRAGMA temp_store=MEMORY;", NULL);
2238  switch_cache_db_execute_sql(qm->event_db, "PRAGMA journal_mode=OFF;", NULL);
2239  }
2240  break;
2241  }
2242 
2243  qm->thread_initiated = 1;
2244  qm->thread_running = 1;
2245 
2246  while (qm->thread_running == 1) {
2247  uint32_t i;
2248  uint32_t written = 0, iterations = 0;
2249 
2250  if (qm->paused) {
2251  goto check;
2252  }
2253 
2254  if (sql_manager.paused) {
2255  for (i = 0; i < qm->numq; i++) {
2256  do_flush(qm, i, NULL);
2257  }
2258  goto check;
2259  }
2260 
2261  do {
2262  if (!qm_ttl(qm)) {
2263  goto check;
2264  }
2265  written = do_trans(qm);
2266  iterations += written;
2267  } while(written == qm->max_trans);
2268 
2270  char line[128] = "";
2271  switch_size_t l;
2272 
2273  switch_snprintf(line, sizeof(line), "%s RUN QUEUE [", qm->name);
2274 
2275  for (i = 0; i < qm->numq; i++) {
2276  l = strlen(line);
2277  switch_snprintf(line + l, sizeof(line) - l, "%d%s", switch_queue_size(qm->sql_queue[i]), i == qm->numq - 1 ? "" : "|");
2278  }
2279 
2280  l = strlen(line);
2281  switch_snprintf(line + l, sizeof(line) - l, "]--[%d]\n", iterations);
2282 
2284 
2285  }
2286 
2287  check:
2288 
2289  if (qm_ttl(qm) == 0) {
2291  if (qm->skip_wait > 0) {
2292  qm->skip_wait--;
2294  } else {
2297  }
2298  }
2299 
2300  i = 40;
2301 
2302  while (--i > 0 && qm_ttl(qm) < 500) {
2303  switch_yield(5000);
2304  }
2305 
2306 
2307  }
2308 
2310 
2311  for(i = 0; i < qm->numq; i++) {
2312  do_flush(qm, i, qm->event_db);
2313  }
2314 
2316 
2317  qm->thread_running = 0;
2318 
2319  return NULL;
2320 }
2321 
2322 
2324 {
2325  char *cols[128] = { 0 };
2326  int col_count = 0;
2327  char *data_copy;
2328  switch_stream_handle_t stream = { 0 };
2329  int i;
2330  char *r;
2331  char col_name[128] = "";
2332  const char *data = switch_event_get_header(event, "presence-data-cols");
2333 
2334  if (zstr(data)) {
2335  return NULL;
2336  }
2337 
2338  data_copy = strdup(data);
2339 
2340  col_count = switch_split(data_copy, ':', cols);
2341 
2342  SWITCH_STANDARD_STREAM(stream);
2343 
2344  for (i = 0; i < col_count; i++) {
2345  const char *val = NULL;
2346 
2347  switch_snprintfv(col_name, sizeof(col_name), "PD-%q", cols[i]);
2348  val = switch_event_get_header_nil(event, col_name);
2349  if (zstr(val)) {
2350  stream.write_function(&stream, "%q=NULL,", cols[i]);
2351  } else {
2352  stream.write_function(&stream, "%q='%q',", cols[i], val);
2353  }
2354  }
2355 
2356  r = (char *) stream.data;
2357 
2358  if (end_of(r) == ',') {
2359  end_of(r) = '\0';
2360  }
2361 
2362  switch_safe_free(data_copy);
2363 
2364  return r;
2365 
2366 }
2367 
2368 
2369 #define MAX_SQL 5
2370 #define new_sql() switch_assert(sql_idx+1 < MAX_SQL); if (exists) sql[sql_idx++]
2371 #define new_sql_a() switch_assert(sql_idx+1 < MAX_SQL); sql[sql_idx++]
2372 
2374 {
2375  char *sql[MAX_SQL] = { 0 };
2376  int sql_idx = 0;
2377  char *extra_cols;
2378  int exists = 1;
2379  char *uuid = NULL;
2380 
2381  switch_assert(event);
2382 
2383  switch (event->event_id) {
2398  {
2399  if ((uuid = switch_event_get_header(event, "unique-id"))) {
2400  exists = switch_ivr_uuid_exists(uuid);
2401  }
2402  }
2403  break;
2404  default:
2405  break;
2406  }
2407 
2408  switch (event->event_id) {
2410  {
2411  const char *id = switch_event_get_header(event, "task-id");
2412  const char *manager = switch_event_get_header(event, "task-sql_manager");
2413 
2414  if (id) {
2415  new_sql() = switch_mprintf("insert into tasks (task_id, task_desc, task_group, task_runtime, task_sql_manager, hostname) "
2416  "values(%q,'%q','%q',%q,%q,'%q')",
2417  id,
2418  switch_event_get_header_nil(event, "task-desc"),
2419  switch_event_get_header_nil(event, "task-group"),
2420  switch_event_get_header_nil(event, "task-runtime"),
2421  manager ? manager : "0",
2423  );
2424  }
2425  }
2426  break;
2429  new_sql() = switch_mprintf("delete from tasks where task_id=%q and hostname='%q'",
2431  break;
2433  {
2434  const char *id = switch_event_get_header(event, "task-id");
2435  const char *manager = switch_event_get_header(event, "task-sql_manager");
2436 
2437  if (id) {
2438  new_sql() = switch_mprintf("update tasks set task_desc='%q',task_group='%q', task_runtime=%q, task_sql_manager=%q where task_id=%q and hostname='%q'",
2439  switch_event_get_header_nil(event, "task-desc"),
2440  switch_event_get_header_nil(event, "task-group"),
2441  switch_event_get_header_nil(event, "task-runtime"),
2442  manager ? manager : "0",
2443  id,
2445  );
2446  }
2447  }
2448  break;
2450  {
2451  const char *uuid = switch_event_get_header(event, "unique-id");
2452 
2453  if (uuid) {
2454  new_sql() = switch_mprintf("delete from channels where uuid='%q'",
2455  uuid);
2456 
2457  new_sql() = switch_mprintf("delete from calls where (caller_uuid='%q' or callee_uuid='%q')",
2458  uuid, uuid);
2459 
2460  }
2461  }
2462  break;
2464  {
2465  new_sql() = switch_mprintf("update channels set uuid='%q' where uuid='%q'",
2466  switch_event_get_header_nil(event, "unique-id"),
2467  switch_event_get_header_nil(event, "old-unique-id")
2468  );
2469 
2470  new_sql() = switch_mprintf("update channels set call_uuid='%q' where call_uuid='%q'",
2471  switch_event_get_header_nil(event, "unique-id"),
2472  switch_event_get_header_nil(event, "old-unique-id")
2473  );
2474  break;
2475  }
2477  new_sql() = switch_mprintf("insert into channels (uuid,direction,created,created_epoch, name,state,callstate,dialplan,context,hostname,initial_cid_name,initial_cid_num,initial_ip_addr,initial_dest,initial_dialplan,initial_context) "
2478  "values('%q','%q','%q','%ld','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q')",
2479  switch_event_get_header_nil(event, "unique-id"),
2480  switch_event_get_header_nil(event, "call-direction"),
2481  switch_event_get_header_nil(event, "event-date-local"),
2482  (long) switch_epoch_time_now(NULL),
2483  switch_event_get_header_nil(event, "channel-name"),
2484  switch_event_get_header_nil(event, "channel-state"),
2485  switch_event_get_header_nil(event, "channel-call-state"),
2486  switch_event_get_header_nil(event, "caller-dialplan"),
2487  switch_event_get_header_nil(event, "caller-context"), switch_core_get_switchname(),
2488  switch_event_get_header_nil(event, "caller-caller-id-name"),
2489  switch_event_get_header_nil(event, "caller-caller-id-number"),
2490  switch_event_get_header_nil(event, "caller-network-addr"),
2491  switch_event_get_header_nil(event, "caller-destination-number"),
2492  switch_event_get_header_nil(event, "caller-dialplan"),
2493  switch_event_get_header_nil(event, "caller-context")
2494  );
2495  break;
2498  case SWITCH_EVENT_CODEC:
2499  new_sql() =
2501  ("update channels set read_codec='%q',read_rate='%q',read_bit_rate='%q',write_codec='%q',write_rate='%q',write_bit_rate='%q' where uuid='%q'",
2502  switch_event_get_header_nil(event, "channel-read-codec-name"),
2503  switch_event_get_header_nil(event, "channel-read-codec-rate"),
2504  switch_event_get_header_nil(event, "channel-read-codec-bit-rate"),
2505  switch_event_get_header_nil(event, "channel-write-codec-name"),
2506  switch_event_get_header_nil(event, "channel-write-codec-rate"),
2507  switch_event_get_header_nil(event, "channel-write-codec-bit-rate"),
2508  switch_event_get_header_nil(event, "unique-id"));
2509  break;
2513 
2514  new_sql() = switch_mprintf("update channels set application='%q',application_data='%q',"
2515  "presence_id='%q',presence_data='%q',accountcode='%q' where uuid='%q'",
2516  switch_event_get_header_nil(event, "application"),
2517  switch_event_get_header_nil(event, "application-data"),
2518  switch_event_get_header_nil(event, "channel-presence-id"),
2519  switch_event_get_header_nil(event, "channel-presence-data"),
2520  switch_event_get_header_nil(event, "variable_accountcode"),
2521  switch_event_get_header_nil(event, "unique-id")
2522  );
2523 
2524  }
2525  break;
2526 
2528  {
2529  if ((extra_cols = parse_presence_data_cols(event))) {
2530  new_sql() = switch_mprintf("update channels set "
2531  "presence_id='%q',presence_data='%q',accountcode='%q',call_uuid='%q',%s where uuid='%q'",
2532  switch_event_get_header_nil(event, "channel-presence-id"),
2533  switch_event_get_header_nil(event, "channel-presence-data"),
2534  switch_event_get_header_nil(event, "variable_accountcode"),
2535  switch_event_get_header_nil(event, "channel-call-uuid"),
2536  extra_cols,
2537  switch_event_get_header_nil(event, "unique-id"));
2538  free(extra_cols);
2539  } else {
2540  new_sql() = switch_mprintf("update channels set "
2541  "presence_id='%q',presence_data='%q',accountcode='%q',call_uuid='%q' where uuid='%q'",
2542  switch_event_get_header_nil(event, "channel-presence-id"),
2543  switch_event_get_header_nil(event, "channel-presence-data"),
2544  switch_event_get_header_nil(event, "variable_accountcode"),
2545  switch_event_get_header_nil(event, "channel-call-uuid"),
2546  switch_event_get_header_nil(event, "unique-id"));
2547  }
2548 
2549  }
2550 
2551  break;
2553  {
2554  new_sql() = switch_mprintf("update channels set callee_name='%q',callee_num='%q',sent_callee_name='%q',sent_callee_num='%q',callee_direction='%q',"
2555  "cid_name='%q',cid_num='%q' where uuid='%q'",
2556  switch_event_get_header_nil(event, "caller-callee-id-name"),
2557  switch_event_get_header_nil(event, "caller-callee-id-number"),
2558  switch_event_get_header_nil(event, "sent-callee-id-name"),
2559  switch_event_get_header_nil(event, "sent-callee-id-number"),
2560  switch_event_get_header_nil(event, "direction"),
2561  switch_event_get_header_nil(event, "caller-caller-id-name"),
2562  switch_event_get_header_nil(event, "caller-caller-id-number"),
2563  switch_event_get_header_nil(event, "unique-id")
2564  );
2565  }
2566  break;
2568  {
2569  char *num = switch_event_get_header_nil(event, "channel-call-state-number");
2571 
2572  if (num) {
2573  callstate = atoi(num);
2574  }
2575 
2576  if (callstate != CCS_DOWN && callstate != CCS_HANGUP) {
2577  if ((extra_cols = parse_presence_data_cols(event))) {
2578  new_sql() = switch_mprintf("update channels set callstate='%q',%s where uuid='%q'",
2579  switch_event_get_header_nil(event, "channel-call-state"),
2580  extra_cols,
2581  switch_event_get_header_nil(event, "unique-id"));
2582  free(extra_cols);
2583  } else {
2584  new_sql() = switch_mprintf("update channels set callstate='%q' where uuid='%q'",
2585  switch_event_get_header_nil(event, "channel-call-state"),
2586  switch_event_get_header_nil(event, "unique-id"));
2587  }
2588  }
2589 
2590  }
2591  break;
2593  {
2594  char *state = switch_event_get_header_nil(event, "channel-state-number");
2596 
2597  if (!zstr(state)) {
2598  state_i = atoi(state);
2599  }
2600 
2601  switch (state_i) {
2602  case CS_NEW:
2603  case CS_DESTROY:
2604  case CS_REPORTING:
2605 #ifndef SWITCH_DEPRECATED_CORE_DB
2606  case CS_HANGUP: /* marked for deprication */
2607 #endif
2608  case CS_INIT:
2609  break;
2610 #ifdef SWITCH_DEPRECATED_CORE_DB
2611  case CS_HANGUP: /* marked for deprication */
2612  new_sql_a() = switch_mprintf("update channels set state='%q' where uuid='%q'",
2613  switch_event_get_header_nil(event, "channel-state"),
2614  switch_event_get_header_nil(event, "unique-id"));
2615  break;
2616 #endif
2617  case CS_EXECUTE:
2618  if ((extra_cols = parse_presence_data_cols(event))) {
2619  new_sql() = switch_mprintf("update channels set state='%q',%s where uuid='%q'",
2620  switch_event_get_header_nil(event, "channel-state"),
2621  extra_cols,
2622  switch_event_get_header_nil(event, "unique-id"));
2623  free(extra_cols);
2624 
2625  } else {
2626  new_sql() = switch_mprintf("update channels set state='%q' where uuid='%q'",
2627  switch_event_get_header_nil(event, "channel-state"),
2628  switch_event_get_header_nil(event, "unique-id"));
2629  }
2630  break;
2631  case CS_ROUTING:
2632  if ((extra_cols = parse_presence_data_cols(event))) {
2633  new_sql() = switch_mprintf("update channels set state='%q',cid_name='%q',cid_num='%q',callee_name='%q',callee_num='%q',"
2634  "sent_callee_name='%q',sent_callee_num='%q',"
2635  "ip_addr='%q',dest='%q',dialplan='%q',context='%q',presence_id='%q',presence_data='%q',accountcode='%q',%s "
2636  "where uuid='%q'",
2637  switch_event_get_header_nil(event, "channel-state"),
2638  switch_event_get_header_nil(event, "caller-caller-id-name"),
2639  switch_event_get_header_nil(event, "caller-caller-id-number"),
2640  switch_event_get_header_nil(event, "caller-callee-id-name"),
2641  switch_event_get_header_nil(event, "caller-callee-id-number"),
2642  switch_event_get_header_nil(event, "sent-callee-id-name"),
2643  switch_event_get_header_nil(event, "sent-callee-id-number"),
2644  switch_event_get_header_nil(event, "caller-network-addr"),
2645  switch_event_get_header_nil(event, "caller-destination-number"),
2646  switch_event_get_header_nil(event, "caller-dialplan"),
2647  switch_event_get_header_nil(event, "caller-context"),
2648  switch_event_get_header_nil(event, "channel-presence-id"),
2649  switch_event_get_header_nil(event, "channel-presence-data"),
2650  switch_event_get_header_nil(event, "variable_accountcode"),
2651  extra_cols,
2652  switch_event_get_header_nil(event, "unique-id"));
2653  free(extra_cols);
2654  } else {
2655  new_sql() = switch_mprintf("update channels set state='%q',cid_name='%q',cid_num='%q',callee_name='%q',callee_num='%q',"
2656  "sent_callee_name='%q',sent_callee_num='%q',"
2657  "ip_addr='%q',dest='%q',dialplan='%q',context='%q',presence_id='%q',presence_data='%q',accountcode='%q' "
2658  "where uuid='%q'",
2659  switch_event_get_header_nil(event, "channel-state"),
2660  switch_event_get_header_nil(event, "caller-caller-id-name"),
2661  switch_event_get_header_nil(event, "caller-caller-id-number"),
2662  switch_event_get_header_nil(event, "caller-callee-id-name"),
2663  switch_event_get_header_nil(event, "caller-callee-id-number"),
2664  switch_event_get_header_nil(event, "sent-callee-id-name"),
2665  switch_event_get_header_nil(event, "sent-callee-id-number"),
2666  switch_event_get_header_nil(event, "caller-network-addr"),
2667  switch_event_get_header_nil(event, "caller-destination-number"),
2668  switch_event_get_header_nil(event, "caller-dialplan"),
2669  switch_event_get_header_nil(event, "caller-context"),
2670  switch_event_get_header_nil(event, "channel-presence-id"),
2671  switch_event_get_header_nil(event, "channel-presence-data"),
2672  switch_event_get_header_nil(event, "variable_accountcode"),
2673  switch_event_get_header_nil(event, "unique-id"));
2674  }
2675  break;
2676  default:
2677  new_sql() = switch_mprintf("update channels set state='%q' where uuid='%q'",
2678  switch_event_get_header_nil(event, "channel-state"),
2679  switch_event_get_header_nil(event, "unique-id"));
2680  break;
2681  }
2682 
2683  break;
2684 
2685 
2686  }
2688  {
2689  const char *a_uuid, *b_uuid, *uuid;
2690 
2691  a_uuid = switch_event_get_header(event, "Bridge-A-Unique-ID");
2692  b_uuid = switch_event_get_header(event, "Bridge-B-Unique-ID");
2693  uuid = switch_event_get_header(event, "unique-id");
2694 
2695  if (zstr(a_uuid) || zstr(b_uuid)) {
2696  a_uuid = switch_event_get_header_nil(event, "caller-unique-id");
2697  b_uuid = switch_event_get_header_nil(event, "other-leg-unique-id");
2698  }
2699 
2700  if (uuid && (extra_cols = parse_presence_data_cols(event))) {
2701  new_sql() = switch_mprintf("update channels set %s where uuid='%q'", extra_cols, uuid);
2702  switch_safe_free(extra_cols);
2703  }
2704 
2705  new_sql() = switch_mprintf("update channels set call_uuid='%q' where uuid='%q' or uuid='%q'",
2706  switch_event_get_header_nil(event, "channel-call-uuid"), a_uuid, b_uuid);
2707 
2708 
2709  new_sql() = switch_mprintf("insert into calls (call_uuid,call_created,call_created_epoch,"
2710  "caller_uuid,callee_uuid,hostname) "
2711  "values ('%q','%q','%ld','%q','%q','%q')",
2712  switch_event_get_header_nil(event, "channel-call-uuid"),
2713  switch_event_get_header_nil(event, "event-date-local"),
2714  (long) switch_epoch_time_now(NULL),
2715  a_uuid,
2716  b_uuid,
2718  );
2719  }
2720  break;
2722  {
2723  char *cuuid = switch_event_get_header_nil(event, "caller-unique-id");
2724  char *uuid = switch_event_get_header(event, "unique-id");
2725 
2726  if (uuid && (extra_cols = parse_presence_data_cols(event))) {
2727  new_sql() = switch_mprintf("update channels set %s where uuid='%q'", extra_cols, uuid);
2728  switch_safe_free(extra_cols);
2729  }
2730 
2731  new_sql() = switch_mprintf("update channels set call_uuid=uuid where call_uuid='%q'",
2732  switch_event_get_header_nil(event, "channel-call-uuid"));
2733 
2734  new_sql() = switch_mprintf("delete from calls where (caller_uuid='%q' or callee_uuid='%q')",
2735  cuuid, cuuid);
2736  break;
2737  }
2738  case SWITCH_EVENT_SHUTDOWN:
2739  new_sql() = switch_mprintf("delete from channels where hostname='%q';"
2740  "delete from interfaces where hostname='%q';"
2741  "delete from calls where hostname='%q'",
2743  );
2744  break;
2745  case SWITCH_EVENT_LOG:
2746  return;
2748  {
2749  const char *type = switch_event_get_header_nil(event, "type");
2750  const char *name = switch_event_get_header_nil(event, "name");
2751  const char *description = switch_event_get_header_nil(event, "description");
2752  const char *syntax = switch_event_get_header_nil(event, "syntax");
2753  const char *key = switch_event_get_header_nil(event, "key");
2754  const char *filename = switch_event_get_header_nil(event, "filename");
2755  if (!zstr(type) && !zstr(name)) {
2756  new_sql() =
2758  ("insert into interfaces (type,name,description,syntax,ikey,filename,hostname) values('%q','%q','%q','%q','%q','%q','%q')", type, name,
2759  switch_str_nil(description), switch_str_nil(syntax), switch_str_nil(key), switch_str_nil(filename),
2761  );
2762  }
2763  break;
2764  }
2766  {
2767  const char *type = switch_event_get_header_nil(event, "type");
2768  const char *name = switch_event_get_header_nil(event, "name");
2769  if (!zstr(type) && !zstr(name)) {
2770  new_sql() = switch_mprintf("delete from interfaces where type='%q' and name='%q' and hostname='%q'", type, name,
2772  }
2773  break;
2774  }
2776  {
2777  const char *type = switch_event_get_header_nil(event, "secure_type");
2778  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Secure Type: %s\n", type);
2779  if (zstr(type)) {
2780  break;
2781  }
2782  new_sql() = switch_mprintf("update channels set secure='%q' where uuid='%q'",
2783  type, switch_event_get_header_nil(event, "caller-unique-id")
2784  );
2785  break;
2786  }
2787  case SWITCH_EVENT_NAT:
2788  {
2789  const char *op = switch_event_get_header_nil(event, "op");
2790  switch_bool_t sticky = switch_true(switch_event_get_header_nil(event, "sticky"));
2791  if (!strcmp("add", op)) {
2792  new_sql() = switch_mprintf("insert into nat (port, proto, sticky, hostname) values (%q, %q, %d,'%q')",
2793  switch_event_get_header_nil(event, "port"),
2794  switch_event_get_header_nil(event, "proto"), sticky, switch_core_get_hostname()
2795  );
2796  } else if (!strcmp("del", op)) {
2797  new_sql() = switch_mprintf("delete from nat where port=%q and proto=%q and hostname='%q'",
2798  switch_event_get_header_nil(event, "port"),
2800  } else if (!strcmp("status", op)) {
2801  /* call show nat api */
2802  } else if (!strcmp("status_response", op)) {
2803  /* ignore */
2804  } else {
2805  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown op for SWITCH_EVENT_NAT: %s\n", op);
2806  }
2807  break;
2808  }
2809  default:
2810  break;
2811  }
2812 
2813  if (sql_idx) {
2814  int i = 0;
2815 
2816 
2817  for (i = 0; i < sql_idx; i++) {
2818  if (switch_stristr("update channels", sql[i]) || switch_stristr("delete from channels", sql[i])) {
2820  } else {
2822  }
2823  sql[i] = NULL;
2824  }
2825  }
2826 }
2827 
2828 
2829 static char create_complete_sql[] =
2830  "CREATE TABLE complete (\n"
2831  " sticky INTEGER,\n"
2832  " a1 VARCHAR(128),\n"
2833  " a2 VARCHAR(128),\n"
2834  " a3 VARCHAR(128),\n"
2835  " a4 VARCHAR(128),\n"
2836  " a5 VARCHAR(128),\n"
2837  " a6 VARCHAR(128),\n"
2838  " a7 VARCHAR(128),\n"
2839  " a8 VARCHAR(128),\n"
2840  " a9 VARCHAR(128),\n"
2841  " a10 VARCHAR(128),\n"
2842  " hostname VARCHAR(256)\n"
2843  ");\n";
2844 
2845 static char create_alias_sql[] =
2846  "CREATE TABLE aliases (\n"
2847  " sticky INTEGER,\n"
2848  " alias VARCHAR(128),\n"
2849  " command VARCHAR(4096),\n"
2850  " hostname VARCHAR(256)\n"
2851  ");\n";
2852 
2853 static char create_channels_sql[] =
2854  "CREATE TABLE channels (\n"
2855  " uuid VARCHAR(256),\n"
2856  " direction VARCHAR(32),\n"
2857  " created VARCHAR(128),\n"
2858  " created_epoch INTEGER,\n"
2859  " name VARCHAR(1024),\n"
2860  " state VARCHAR(64),\n"
2861  " cid_name VARCHAR(1024),\n"
2862  " cid_num VARCHAR(256),\n"
2863  " ip_addr VARCHAR(256),\n"
2864  " dest VARCHAR(1024),\n"
2865  " application VARCHAR(128),\n"
2866  " application_data VARCHAR(4096),\n"
2867  " dialplan VARCHAR(128),\n"
2868  " context VARCHAR(128),\n"
2869  " read_codec VARCHAR(128),\n"
2870  " read_rate VARCHAR(32),\n"
2871  " read_bit_rate VARCHAR(32),\n"
2872  " write_codec VARCHAR(128),\n"
2873  " write_rate VARCHAR(32),\n"
2874  " write_bit_rate VARCHAR(32),\n"
2875  " secure VARCHAR(64),\n"
2876  " hostname VARCHAR(256),\n"
2877  " presence_id VARCHAR(4096),\n"
2878  " presence_data VARCHAR(4096),\n"
2879  " accountcode VARCHAR(256),\n"
2880  " callstate VARCHAR(64),\n"
2881  " callee_name VARCHAR(1024),\n"
2882  " callee_num VARCHAR(256),\n"
2883  " callee_direction VARCHAR(5),\n"
2884  " call_uuid VARCHAR(256),\n"
2885  " sent_callee_name VARCHAR(1024),\n"
2886  " sent_callee_num VARCHAR(256),\n"
2887  " initial_cid_name VARCHAR(1024),\n"
2888  " initial_cid_num VARCHAR(256),\n"
2889  " initial_ip_addr VARCHAR(256),\n"
2890  " initial_dest VARCHAR(1024),\n"
2891  " initial_dialplan VARCHAR(128),\n"
2892  " initial_context VARCHAR(128)\n"
2893  ");\n";
2894 
2896  "CREATE TABLE channels (\n"
2897  " uuid VARCHAR(256),\n"
2898  " direction VARCHAR(32),\n"
2899  " created VARCHAR(128),\n"
2900  " created_epoch INTEGER,\n"
2901  " name VARCHAR(1024),\n"
2902  " state VARCHAR(64),\n"
2903  " cid_name VARCHAR(1024),\n"
2904  " cid_num VARCHAR(256),\n"
2905  " ip_addr VARCHAR(256),\n"
2906  " dest VARCHAR(1024),\n"
2907  " application VARCHAR(128),\n"
2908  " application_data TEXT,\n"
2909  " dialplan VARCHAR(128),\n"
2910  " context VARCHAR(128),\n"
2911  " read_codec VARCHAR(128),\n"
2912  " read_rate VARCHAR(32),\n"
2913  " read_bit_rate VARCHAR(32),\n"
2914  " write_codec VARCHAR(128),\n"
2915  " write_rate VARCHAR(32),\n"
2916  " write_bit_rate VARCHAR(32),\n"
2917  " secure VARCHAR(64),\n"
2918  " hostname VARCHAR(256),\n"
2919  " presence_id VARCHAR(4096),\n"
2920  " presence_data TEXT,\n"
2921  " accountcode VARCHAR(256),\n"
2922  " callstate VARCHAR(64),\n"
2923  " callee_name VARCHAR(1024),\n"
2924  " callee_num VARCHAR(256),\n"
2925  " callee_direction VARCHAR(5),\n"
2926  " call_uuid VARCHAR(256),\n"
2927  " sent_callee_name VARCHAR(1024),\n"
2928  " sent_callee_num VARCHAR(256),\n"
2929  " initial_cid_name VARCHAR(1024),\n"
2930  " initial_cid_num VARCHAR(256),\n"
2931  " initial_ip_addr VARCHAR(256),\n"
2932  " initial_dest VARCHAR(1024),\n"
2933  " initial_dialplan VARCHAR(128),\n"
2934  " initial_context VARCHAR(128)\n"
2935 ");\n";
2936 
2937 static char create_calls_sql[] =
2938  "CREATE TABLE calls (\n"
2939  " call_uuid VARCHAR(255),\n"
2940  " call_created VARCHAR(128),\n"
2941  " call_created_epoch INTEGER,\n"
2942  " caller_uuid VARCHAR(256),\n"
2943  " callee_uuid VARCHAR(256),\n"
2944  " hostname VARCHAR(256)\n"
2945  ");\n";
2946 
2947 static char create_interfaces_sql[] =
2948  "CREATE TABLE interfaces (\n"
2949  " type VARCHAR(128),\n"
2950  " name VARCHAR(1024),\n"
2951  " description VARCHAR(4096),\n"
2952  " ikey VARCHAR(1024),\n"
2953  " filename VARCHAR(4096),\n"
2954  " syntax VARCHAR(4096),\n"
2955  " hostname VARCHAR(256)\n"
2956  ");\n";
2957 
2958 static char create_tasks_sql[] =
2959  "CREATE TABLE tasks (\n"
2960  " task_id INTEGER,\n"
2961  " task_desc VARCHAR(4096),\n"
2962  " task_group VARCHAR(1024),\n"
2963  " task_runtime BIGINT,\n"
2964  " task_sql_manager INTEGER,\n"
2965  " hostname VARCHAR(256)\n"
2966  ");\n";
2967 
2968 static char create_nat_sql[] =
2969  "CREATE TABLE nat (\n"
2970  " sticky INTEGER,\n"
2971  " port INTEGER,\n"
2972  " proto INTEGER,\n"
2973  " hostname VARCHAR(256)\n"
2974  ");\n";
2975 
2976 
2978  "CREATE TABLE registrations (\n"
2979  " reg_user VARCHAR(256),\n"
2980  " realm VARCHAR(256),\n"
2981  " token VARCHAR(256),\n"
2982  /* If url is modified please check for code in switch_core_sqldb_start for dependencies for MSSQL" */
2983  " url TEXT,\n"
2984  " expires INTEGER,\n"
2985  " network_ip VARCHAR(256),\n"
2986  " network_port VARCHAR(256),\n"
2987  " network_proto VARCHAR(256),\n"
2988  " hostname VARCHAR(256),\n"
2989  " metadata VARCHAR(256)\n"
2990  ");\n";
2991 
2992 
2993 
2994 
2995 static char detailed_calls_sql[] =
2996  "create view detailed_calls as select "
2997  "a.uuid as uuid,"
2998  "a.direction as direction,"
2999  "a.created as created,"
3000  "a.created_epoch as created_epoch,"
3001  "a.name as name,"
3002  "a.state as state,"
3003  "a.cid_name as cid_name,"
3004  "a.cid_num as cid_num,"
3005  "a.ip_addr as ip_addr,"
3006  "a.dest as dest,"
3007  "a.application as application,"
3008  "a.application_data as application_data,"
3009  "a.dialplan as dialplan,"
3010  "a.context as context,"
3011  "a.read_codec as read_codec,"
3012  "a.read_rate as read_rate,"
3013  "a.read_bit_rate as read_bit_rate,"
3014  "a.write_codec as write_codec,"
3015  "a.write_rate as write_rate,"
3016  "a.write_bit_rate as write_bit_rate,"
3017  "a.secure as secure,"
3018  "a.hostname as hostname,"
3019  "a.presence_id as presence_id,"
3020  "a.presence_data as presence_data,"
3021  "a.accountcode as accountcode,"
3022  "a.callstate as callstate,"
3023  "a.callee_name as callee_name,"
3024  "a.callee_num as callee_num,"
3025  "a.callee_direction as callee_direction,"
3026  "a.call_uuid as call_uuid,"
3027  "a.sent_callee_name as sent_callee_name,"
3028  "a.sent_callee_num as sent_callee_num,"
3029  "b.uuid as b_uuid,"
3030  "b.direction as b_direction,"
3031  "b.created as b_created,"
3032  "b.created_epoch as b_created_epoch,"
3033  "b.name as b_name,"
3034  "b.state as b_state,"
3035  "b.cid_name as b_cid_name,"
3036  "b.cid_num as b_cid_num,"
3037  "b.ip_addr as b_ip_addr,"
3038  "b.dest as b_dest,"
3039  "b.application as b_application,"
3040  "b.application_data as b_application_data,"
3041  "b.dialplan as b_dialplan,"
3042  "b.context as b_context,"
3043  "b.read_codec as b_read_codec,"
3044  "b.read_rate as b_read_rate,"
3045  "b.read_bit_rate as b_read_bit_rate,"
3046  "b.write_codec as b_write_codec,"
3047  "b.write_rate as b_write_rate,"
3048  "b.write_bit_rate as b_write_bit_rate,"
3049  "b.secure as b_secure,"
3050  "b.hostname as b_hostname,"
3051  "b.presence_id as b_presence_id,"
3052  "b.presence_data as b_presence_data,"
3053  "b.accountcode as b_accountcode,"
3054  "b.callstate as b_callstate,"
3055  "b.callee_name as b_callee_name,"
3056  "b.callee_num as b_callee_num,"
3057  "b.callee_direction as b_callee_direction,"
3058  "b.call_uuid as b_call_uuid,"
3059  "b.sent_callee_name as b_sent_callee_name,"
3060  "b.sent_callee_num as b_sent_callee_num,"
3061  "c.call_created_epoch as call_created_epoch "
3062  "from channels a "
3063  "left join calls c on a.uuid = c.caller_uuid and a.hostname = c.hostname "
3064  "left join channels b on b.uuid = c.callee_uuid and b.hostname = c.hostname "
3065  "where a.uuid = c.caller_uuid or a.uuid not in (select callee_uuid from calls)";
3066 
3067 
3068 static char recovery_sql[] =
3069  "CREATE TABLE recovery (\n"
3070  " runtime_uuid VARCHAR(255),\n"
3071  " technology VARCHAR(255),\n"
3072  " profile_name VARCHAR(255),\n"
3073  " hostname VARCHAR(255),\n"
3074  " uuid VARCHAR(255),\n"
3075  " metadata text\n"
3076  ");\n";
3077 
3078 static char basic_calls_sql[] =
3079  "create view basic_calls as select "
3080  "a.uuid as uuid,"
3081  "a.direction as direction,"
3082  "a.created as created,"
3083  "a.created_epoch as created_epoch,"
3084  "a.name as name,"
3085  "a.state as state,"
3086  "a.cid_name as cid_name,"
3087  "a.cid_num as cid_num,"
3088  "a.ip_addr as ip_addr,"
3089  "a.dest as dest,"
3090 
3091  "a.presence_id as presence_id,"
3092  "a.presence_data as presence_data,"
3093  "a.accountcode as accountcode,"
3094  "a.callstate as callstate,"
3095  "a.callee_name as callee_name,"
3096  "a.callee_num as callee_num,"
3097  "a.callee_direction as callee_direction,"
3098  "a.call_uuid as call_uuid,"
3099  "a.hostname as hostname,"
3100  "a.sent_callee_name as sent_callee_name,"
3101  "a.sent_callee_num as sent_callee_num,"
3102 
3103 
3104  "b.uuid as b_uuid,"
3105  "b.direction as b_direction,"
3106  "b.created as b_created,"
3107  "b.created_epoch as b_created_epoch,"
3108  "b.name as b_name,"
3109  "b.state as b_state,"
3110  "b.cid_name as b_cid_name,"
3111  "b.cid_num as b_cid_num,"
3112  "b.ip_addr as b_ip_addr,"
3113  "b.dest as b_dest,"
3114 
3115  "b.presence_id as b_presence_id,"
3116  "b.presence_data as b_presence_data,"
3117  "b.accountcode as b_accountcode,"
3118  "b.callstate as b_callstate,"
3119  "b.callee_name as b_callee_name,"
3120  "b.callee_num as b_callee_num,"
3121  "b.callee_direction as b_callee_direction,"
3122  "b.sent_callee_name as b_sent_callee_name,"
3123  "b.sent_callee_num as b_sent_callee_num,"
3124  "c.call_created_epoch as call_created_epoch "
3125 
3126  "from channels a "
3127  "left join calls c on a.uuid = c.caller_uuid and a.hostname = c.hostname "
3128  "left join channels b on b.uuid = c.callee_uuid and b.hostname = c.hostname "
3129  "where a.uuid = c.caller_uuid or a.uuid not in (select callee_uuid from calls)";
3130 
3131 
3132 
3133 SWITCH_DECLARE(void) switch_core_recovery_flush(const char *technology, const char *profile_name)
3134 {
3135  char *sql = NULL;
3137 
3139  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n");
3140  return;
3141  }
3142 
3143  if (zstr(technology)) {
3144 
3145  if (zstr(profile_name)) {
3146  sql = switch_mprintf("delete from recovery");
3147  } else {
3149  }
3150 
3151  } else {
3152  if (zstr(profile_name)) {
3153  sql = switch_mprintf("delete from recovery where technology='%q' ", technology);
3154  } else {
3155  sql = switch_mprintf("delete from recovery where technology='%q' and profile_name='%q'", technology, profile_name);
3156  }
3157  }
3158 
3159  if (sql) {
3160  switch_cache_db_execute_sql(dbh, sql, NULL);
3161  switch_safe_free(sql);
3162  }
3163 
3165 }
3166 
3167 
3168 static int recover_callback(void *pArg, int argc, char **argv, char **columnNames)
3169 {
3170  int *rp = (int *) pArg;
3171  switch_xml_t xml;
3173  switch_core_session_t *session;
3174 
3175  if (argc < 4) {
3176  return 0;
3177  }
3178 
3179  if (!(xml = switch_xml_parse_str_dynamic(argv[4], SWITCH_TRUE))) {
3181  return 0;
3182  }
3183 
3184  if (!(ep = switch_loadable_module_get_endpoint_interface(argv[0]))) {
3186  switch_xml_free(xml);
3187 
3188  return 0;
3189  }
3190 
3191  if (!(session = switch_core_session_request_xml(ep, NULL, xml))) {
3192  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid cdr data, call not recovered\n");
3193  goto end;
3194  }
3195 
3196  if (ep->recover_callback) {
3197  switch_caller_extension_t *extension = NULL;
3199  int r = 0;
3200 
3201  if ((r = ep->recover_callback(session)) > 0) {
3202  const char *cbname;
3203 
3205 
3206 
3207  if (switch_channel_get_partner_uuid(channel)) {
3209  }
3210 
3212 
3213  if ((cbname = switch_channel_get_variable(channel, "secondary_recovery_module"))) {
3215 
3216  if ((recover_callback = switch_core_get_secondary_recover_callback(cbname))) {
3217  r = recover_callback(session);
3218  }
3219  }
3220 
3221 
3222  }
3223 
3224  if (r > 0) {
3225 
3227  switch_xml_t callflow, param, x_extension;
3228  if ((extension = switch_caller_extension_new(session, "recovery", "recovery")) == 0) {
3229  abort();
3230  }
3231 
3232  if ((callflow = switch_xml_child(xml, "callflow")) && (x_extension = switch_xml_child(callflow, "extension"))) {
3233  int recovery_skip_announcement_type_applications = switch_channel_var_true(channel, "recovery_skip_announcement_type_applications");
3234  for (param = switch_xml_child(x_extension, "application"); param; param = param->next) {
3235  const char *var = switch_xml_attr_soft(param, "app_name");
3236  const char *val = switch_xml_attr_soft(param, "app_data");
3237  /* skip announcement type apps */
3238  if (!recovery_skip_announcement_type_applications || (strcasecmp(var, "speak") && strcasecmp(var, "playback") && strcasecmp(var, "gentones") && strcasecmp(var, "say"))) {
3239  switch_caller_extension_add_application(session, extension, var, val);
3240  }
3241  }
3242  }
3243 
3244  switch_channel_set_caller_extension(channel, extension);
3245  }
3246 
3249  "Resurrecting fallen channel %s\n", switch_channel_get_name(channel));
3251 
3252  *rp = (*rp) + 1;
3253 
3254  }
3255 
3256  } else {
3257  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Endpoint %s has no recovery function\n", argv[0]);
3258  }
3259 
3260 
3261  end:
3262 
3263  UNPROTECT_INTERFACE(ep);
3264 
3265  switch_xml_free(xml);
3266 
3267  return 0;
3268 }
3269 
3270 SWITCH_DECLARE(int) switch_core_recovery_recover(const char *technology, const char *profile_name)
3271 
3272 {
3273  char *sql = NULL;
3274  char *errmsg = NULL;
3276  int r = 0;
3277 
3278  if (!sql_manager.manage) {
3279  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DATABASE NOT AVAIALBLE, REVCOVERY NOT POSSIBLE\n");
3280  return 0;
3281  }
3282 
3284  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n");
3285  return 0;
3286  }
3287 
3288  if (zstr(technology)) {
3289 
3290  if (zstr(profile_name)) {
3291  sql = switch_mprintf("select technology, profile_name, hostname, uuid, metadata "
3292  "from recovery where runtime_uuid!='%q'",
3294  } else {
3295  sql = switch_mprintf("select technology, profile_name, hostname, uuid, metadata "
3296  "from recovery where runtime_uuid!='%q' and profile_name='%q'",
3297  switch_core_get_uuid(), profile_name);
3298  }
3299 
3300  } else {
3301 
3302  if (zstr(profile_name)) {
3303  sql = switch_mprintf("select technology, profile_name, hostname, uuid, metadata "
3304  "from recovery where technology='%q' and runtime_uuid!='%q'",
3305  technology, switch_core_get_uuid());
3306  } else {
3307  sql = switch_mprintf("select technology, profile_name, hostname, uuid, metadata "
3308  "from recovery where technology='%q' and runtime_uuid!='%q' and profile_name='%q'",
3309  technology, switch_core_get_uuid(), profile_name);
3310  }
3311  }
3312 
3313 
3315 
3316  if (errmsg) {
3317  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: [%s] %s\n", sql, errmsg);
3318  switch_safe_free(errmsg);
3319  }
3320 
3321  switch_safe_free(sql);
3322 
3323  if (zstr(technology)) {
3324  if (zstr(profile_name)) {
3325  sql = switch_mprintf("delete from recovery where runtime_uuid!='%q'",
3327  } else {
3328  sql = switch_mprintf("delete from recovery where runtime_uuid!='%q' and profile_name='%q'",
3329  switch_core_get_uuid(), profile_name);
3330  }
3331  } else {
3332  if (zstr(profile_name)) {
3333  sql = switch_mprintf("delete from recovery where runtime_uuid!='%q' and technology='%q' ",
3334  switch_core_get_uuid(), technology);
3335  } else {
3336  sql = switch_mprintf("delete from recovery where runtime_uuid!='%q' and technology='%q' and profile_name='%q'",
3337  switch_core_get_uuid(), technology, profile_name);
3338  }
3339  }
3340 
3341  switch_cache_db_execute_sql(dbh, sql, NULL);
3342  switch_safe_free(sql);
3343 
3345 
3346  return r;
3347 
3348 }
3349 
3351 {
3353 
3354  switch_mutex_lock(sql_manager.ctl_mutex);
3355  if (sql_manager.qm && sql_manager.qm->event_db) {
3356  type = sql_manager.qm->event_db->type;
3357  }
3358  switch_mutex_unlock(sql_manager.ctl_mutex);
3359 
3360  return type;
3361 }
3362 
3364 {
3365  if (!sql_manager.manage) {
3366  return;
3367  }
3368 
3369  if (!switch_test_flag((&runtime), SCF_USE_SQL)) {
3370  return;
3371  }
3372 
3373 
3375 }
3376 
3378 {
3379  char *sql = NULL;
3381 
3382  if (!sql_manager.manage) {
3383  return;
3384  }
3385 
3387  return;
3388  }
3389 
3390  if (!switch_channel_test_flag(channel, CF_TRACKABLE)) {
3391  return;
3392  }
3393 
3394  if ((switch_channel_test_flag(channel, CF_RECOVERING))) {
3395  return;
3396  }
3397 
3398  if (switch_channel_test_flag(channel, CF_TRACKED) || force) {
3399 
3400  if (force) {
3401  sql = switch_mprintf("delete from recovery where uuid='%q'", switch_core_session_get_uuid(session));
3402 
3403  } else {
3404  sql = switch_mprintf("delete from recovery where runtime_uuid='%q' and uuid='%q'",
3406  }
3407 
3409 
3411  }
3412 
3413 }
3414 
3416 {
3417  switch_xml_t cdr = NULL;
3418  char *xml_cdr_text = NULL;
3419  char *sql = NULL;
3421  const char *profile_name;
3422  const char *technology;
3423 
3424  if (!sql_manager.manage) {
3425  return;
3426  }
3427 
3429  return;
3430  }
3431 
3433  return;
3434  }
3435 
3436  profile_name = switch_channel_get_variable_dup(channel, "recovery_profile_name", SWITCH_FALSE, -1);
3437  technology = session->endpoint_interface->interface_name;
3438 
3439  if (switch_ivr_generate_xml_cdr(session, &cdr) == SWITCH_STATUS_SUCCESS) {
3440  xml_cdr_text = switch_xml_toxml_nolock(cdr, SWITCH_FALSE);
3441  switch_xml_free(cdr);
3442  }
3443 
3444  if (xml_cdr_text) {
3445  if (switch_channel_test_flag(channel, CF_TRACKED)) {
3446  sql = switch_mprintf("update recovery set metadata='%q' where uuid='%q'", xml_cdr_text, switch_core_session_get_uuid(session));
3447  } else {
3448  sql = switch_mprintf("insert into recovery (runtime_uuid, technology, profile_name, hostname, uuid, metadata) "
3449  "values ('%q','%q','%q','%q','%q','%q')",
3450  switch_core_get_uuid(), switch_str_nil(technology),
3451  switch_str_nil(profile_name), switch_core_get_switchname(), switch_core_session_get_uuid(session), xml_cdr_text);
3452  }
3453 
3455 
3456  switch_safe_free(xml_cdr_text);
3458 
3459  }
3460 
3461 }
3462 
3463 
3464 
3465 SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, const char *realm, const char *token, const char *url, uint32_t expires,
3466  const char *network_ip, const char *network_port, const char *network_proto,
3467  const char *metadata)
3468 {
3469  char *sql;
3470 
3471  if (!switch_test_flag((&runtime), SCF_USE_SQL)) {
3472  return SWITCH_STATUS_FALSE;
3473  }
3474 
3476  sql = switch_mprintf("delete from registrations where hostname='%q' and (url='%q' or token='%q')",
3478  } else {
3479  sql = switch_mprintf("delete from registrations where reg_user='%q' and realm='%q' and hostname='%q'",
3480  user, realm, switch_core_get_switchname());
3481  }
3482 
3484 
3485  if ( !zstr(metadata) ) {
3486  sql = switch_mprintf("insert into registrations (reg_user,realm,token,url,expires,network_ip,network_port,network_proto,hostname,metadata) "
3487  "values ('%q','%q','%q','%q',%ld,'%q','%q','%q','%q','%q')",
3488  switch_str_nil(user),
3489  switch_str_nil(realm),
3490  switch_str_nil(token),
3491  switch_str_nil(url),
3492  expires,
3493  switch_str_nil(network_ip),
3494  switch_str_nil(network_port),
3495  switch_str_nil(network_proto),
3497  metadata
3498  );
3499  } else {
3500  sql = switch_mprintf("insert into registrations (reg_user,realm,token,url,expires,network_ip,network_port,network_proto,hostname) "
3501  "values ('%q','%q','%q','%q',%ld,'%q','%q','%q','%q')",
3502  switch_str_nil(user),
3503  switch_str_nil(realm),
3504  switch_str_nil(token),
3505  switch_str_nil(url),
3506  expires,
3507  switch_str_nil(network_ip),
3508  switch_str_nil(network_port),
3509  switch_str_nil(network_proto),
3511  );
3512  }
3513 
3514 
3516 
3517  return SWITCH_STATUS_SUCCESS;
3518 }
3519 
3520 SWITCH_DECLARE(switch_status_t) switch_core_del_registration(const char *user, const char *realm, const char *token)
3521 {
3522 
3523  char *sql;
3524 
3525  if (!switch_test_flag((&runtime), SCF_USE_SQL)) {
3526  return SWITCH_STATUS_FALSE;
3527  }
3528 
3529  if (!zstr(token) && runtime.multiple_registrations) {
3530  sql = switch_mprintf("delete from registrations where reg_user='%q' and realm='%q' and hostname='%q' and token='%q'", user, realm, switch_core_get_switchname(), token);
3531  } else {
3532  sql = switch_mprintf("delete from registrations where reg_user='%q' and realm='%q' and hostname='%q'", user, realm, switch_core_get_switchname());
3533  }
3534 
3536 
3537 
3538  return SWITCH_STATUS_SUCCESS;
3539 }
3540 
3542 {
3543 
3544  char *sql;
3545  time_t now;
3546 
3547  if (!switch_test_flag((&runtime), SCF_USE_SQL)) {
3548  return SWITCH_STATUS_FALSE;
3549  }
3550 
3551  now = switch_epoch_time_now(NULL);
3552 
3553  if (force) {
3554  sql = switch_mprintf("delete from registrations where hostname='%q'", switch_core_get_switchname());
3555  } else {
3556  sql = switch_mprintf("delete from registrations where expires > 0 and expires <= %ld and hostname='%q'", now, switch_core_get_switchname());
3557  }
3558 
3560 
3561  return SWITCH_STATUS_SUCCESS;
3562 
3563 }
3564 
3566 {
3567  switch_threadattr_t *thd_attr;
3568 
3569  sql_manager.memory_pool = pool;
3570  sql_manager.manage = manage;
3571 
3574 
3575  if (!sql_manager.manage) goto skip;
3576 
3577  top:
3578 
3579  /* Activate SQL database */
3581  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n");
3582 
3584  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure! ODBC IS REQUIRED!\n");
3585  return SWITCH_STATUS_FALSE;
3586  }
3587 
3588  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "CORE DATABASE INITIALIZATION FAILURE! CHECK `core-db-dsn`!\n");
3589 
3591  return SWITCH_STATUS_FALSE;
3592  }
3593 
3594 
3596 
3597  switch (sql_manager.dbh->type) {
3599  case SCDB_TYPE_ODBC:
3601  char sql[512] = "";
3602  char *tables[] = { "channels", "calls", "tasks", NULL };
3603  int i;
3604  const char *hostname = switch_core_get_switchname();
3605 
3606  for (i = 0; tables[i]; i++) {
3607  switch_snprintfv(sql, sizeof(sql), "delete from %q where hostname='%q'", tables[i], hostname);
3608  switch_cache_db_execute_sql(sql_manager.dbh, sql, NULL);
3609  }
3610  }
3611  break;
3612  case SCDB_TYPE_CORE_DB:
3613  {
3614  switch_cache_db_execute_sql(sql_manager.dbh, "drop table channels", NULL);
3615  switch_cache_db_execute_sql(sql_manager.dbh, "drop table calls", NULL);
3616  switch_cache_db_execute_sql(sql_manager.dbh, "drop view detailed_calls", NULL);
3617  switch_cache_db_execute_sql(sql_manager.dbh, "drop view basic_calls", NULL);
3618  switch_cache_db_execute_sql(sql_manager.dbh, "drop table interfaces", NULL);
3619  switch_cache_db_execute_sql(sql_manager.dbh, "drop table tasks", NULL);
3620  switch_cache_db_execute_sql(sql_manager.dbh, "PRAGMA synchronous=OFF;", NULL);
3621  switch_cache_db_execute_sql(sql_manager.dbh, "PRAGMA count_changes=OFF;", NULL);
3622  switch_cache_db_execute_sql(sql_manager.dbh, "PRAGMA default_cache_size=8000", NULL);
3623  switch_cache_db_execute_sql(sql_manager.dbh, "PRAGMA temp_store=MEMORY;", NULL);
3624  switch_cache_db_execute_sql(sql_manager.dbh, "PRAGMA journal_mode=OFF;", NULL);
3625  }
3626  break;
3627  }
3628 
3629  switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from aliases", "DROP TABLE aliases", create_alias_sql);
3630  switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from complete", "DROP TABLE complete", create_complete_sql);
3631  switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from nat", "DROP TABLE nat", create_nat_sql);
3632  switch_cache_db_test_reactive(sql_manager.dbh, "delete from registrations where reg_user=''",
3633  "DROP TABLE registrations", create_registrations_sql);
3634 
3635  switch_cache_db_test_reactive(sql_manager.dbh, "select metadata from registrations", NULL, "ALTER TABLE registrations ADD COLUMN metadata VARCHAR(256)");
3636 
3637 
3638  switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from recovery", "DROP TABLE recovery", recovery_sql);
3639  switch_cache_db_create_schema(sql_manager.dbh, "create index recovery1 on recovery(technology)", NULL);
3640  switch_cache_db_create_schema(sql_manager.dbh, "create index recovery2 on recovery(profile_name)", NULL);
3641  switch_cache_db_create_schema(sql_manager.dbh, "create index recovery3 on recovery(uuid)", NULL);
3642  switch_cache_db_create_schema(sql_manager.dbh, "create index recovery4 on recovery(runtime_uuid)", NULL);
3643 
3644 
3645 
3646 
3647  switch (sql_manager.dbh->type) {
3649  case SCDB_TYPE_ODBC:
3650  {
3651  char *err;
3652  int result = 0;
3653 
3654  switch_cache_db_test_reactive_ex(sql_manager.dbh, "select call_uuid, read_bit_rate, sent_callee_name, initial_cid_name, initial_cid_num, initial_ip_addr, initial_dest, initial_dialplan, initial_context, accountcode from channels", "DROP TABLE channels", create_channels_sql, create_row_size_limited_channels_sql);
3655  switch_cache_db_test_reactive(sql_manager.dbh, "select call_uuid from calls", "DROP TABLE calls", create_calls_sql);
3656  switch_cache_db_test_reactive(sql_manager.dbh, "select * from basic_calls where sent_callee_name=''", "DROP VIEW basic_calls", basic_calls_sql);
3657  switch_cache_db_test_reactive(sql_manager.dbh, "select * from detailed_calls where sent_callee_name=''", "DROP VIEW detailed_calls", detailed_calls_sql);
3659  switch_cache_db_test_reactive(sql_manager.dbh, "delete from registrations where reg_user=''",
3660  "DROP TABLE registrations", create_registrations_sql);
3661  } else {
3662  char *tmp = switch_string_replace(create_registrations_sql, "url TEXT", "url VARCHAR(max)");
3663  switch_cache_db_test_reactive(sql_manager.dbh, "delete from registrations where reg_user=''",
3664  "DROP TABLE registrations", tmp);
3665  free(tmp);
3666  }
3667  switch_cache_db_test_reactive(sql_manager.dbh, "select ikey from interfaces", "DROP TABLE interfaces", create_interfaces_sql);
3668  switch_cache_db_test_reactive(sql_manager.dbh, "select task_id, task_desc, task_group, task_runtime, task_sql_manager, hostname from tasks",
3669  "DROP TABLE tasks", create_tasks_sql);
3670 
3671 
3672  switch(sql_manager.dbh->type) {
3673  case SCDB_TYPE_CORE_DB:
3674  {
3675  switch_cache_db_execute_sql_real(sql_manager.dbh, "BEGIN EXCLUSIVE", &err);
3676  }
3677  break;
3678  case SCDB_TYPE_ODBC:
3679  {
3680  switch_odbc_status_t result;
3681 
3682  if ((result = switch_odbc_SQLSetAutoCommitAttr(sql_manager.dbh->native_handle.odbc_dbh, 0)) != SWITCH_ODBC_SUCCESS) {
3683  char tmp[100];
3684  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to Set AutoCommit Off", result);
3685  err = strdup(tmp);
3686  }
3687  }
3688  break;
3690  {
3691  switch_database_interface_t *database_interface = sql_manager.dbh->native_handle.database_interface_dbh->connection_options.database_interface;
3692  switch_status_t result;
3693 
3694  if ((result = database_interface->sql_set_auto_commit_attr(sql_manager.dbh->native_handle.database_interface_dbh, 0)) != SWITCH_STATUS_SUCCESS) {
3695  char tmp[100];
3696  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to Set AutoCommit Off", result);
3697  err = strdup(tmp);
3698  }
3699  }
3700  break;
3701  }
3702 
3703  switch_cache_db_execute_sql(sql_manager.dbh, "delete from channels where hostname=''", &err);
3704  if (!err) {
3705  switch_cache_db_execute_sql(sql_manager.dbh, "delete from channels where hostname=''", &err);
3706 
3707  switch(sql_manager.dbh->type) {
3708  case SCDB_TYPE_CORE_DB:
3709  {
3710  switch_cache_db_execute_sql_real(sql_manager.dbh, "COMMIT", &err);
3711  }
3712  break;
3713  case SCDB_TYPE_ODBC:
3714  {
3715  if (switch_odbc_SQLEndTran(sql_manager.dbh->native_handle.odbc_dbh, 1) != SWITCH_ODBC_SUCCESS ||
3716  switch_odbc_SQLSetAutoCommitAttr(sql_manager.dbh->native_handle.odbc_dbh, 1) != SWITCH_ODBC_SUCCESS) {
3717  char tmp[100];
3718  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to commit transaction.", result);
3719  err = strdup(tmp);
3720  }
3721  }
3722  break;
3724  {
3725  switch_database_interface_t *database_interface = sql_manager.dbh->native_handle.database_interface_dbh->connection_options.database_interface;
3726  switch_status_t result;
3727 
3728  if ((result = database_interface->commit(sql_manager.dbh->native_handle.database_interface_dbh)) != SWITCH_STATUS_SUCCESS) {
3729  char tmp[100];
3730  switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to commit transaction", result);
3731  err = strdup(tmp);
3732  }
3733  }
3734  break;
3735  }
3736  }
3737 
3738 
3739  if (err) {
3740  //runtime.odbc_dsn = NULL;
3741  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database Error [%s]\n", err);
3742  //switch_cache_db_release_db_handle(&sql_manager.dbh);
3743  if (switch_stristr("read-only", err)) {
3744  switch_safe_free(err);
3745  } else {
3746  switch_safe_free(err);
3747  goto top;
3748  }
3749  }
3750  }
3751  break;
3752  case SCDB_TYPE_CORE_DB:
3753  {
3760 
3761  if (sql_manager.dbh->native_handle.core_db_dbh->in_memory == SWITCH_TRUE) {
3763  }
3764  }
3765  break;
3766  }
3767 
3769  char sql[512] = "";
3770  char *tables[] = { "complete", "aliases", "nat", NULL };
3771  int i;
3772  const char *hostname = switch_core_get_hostname();
3773 
3774  for (i = 0; tables[i]; i++) {
3775  switch_snprintfv(sql, sizeof(sql), "delete from %q where sticky=0 and hostname='%q'", tables[i], hostname);
3776  switch_cache_db_execute_sql(sql_manager.dbh, sql, NULL);
3777  }
3778 
3779  switch_snprintfv(sql, sizeof(sql), "delete from interfaces where hostname='%q'", hostname);
3780  switch_cache_db_execute_sql(sql_manager.dbh, sql, NULL);
3781  }
3782 
3783  switch_cache_db_create_schema(sql_manager.dbh, "create index alias1 on aliases (alias)", NULL);
3784  switch_cache_db_create_schema(sql_manager.dbh, "create index tasks1 on tasks (hostname,task_id)", NULL);
3785  switch_cache_db_create_schema(sql_manager.dbh, "create index complete1 on complete (a1,hostname)", NULL);
3786  switch_cache_db_create_schema(sql_manager.dbh, "create index complete2 on complete (a2,hostname)", NULL);
3787  switch_cache_db_create_schema(sql_manager.dbh, "create index complete3 on complete (a3,hostname)", NULL);
3788  switch_cache_db_create_schema(sql_manager.dbh, "create index complete4 on complete (a4,hostname)", NULL);
3789  switch_cache_db_create_schema(sql_manager.dbh, "create index complete5 on complete (a5,hostname)", NULL);
3790  switch_cache_db_create_schema(sql_manager.dbh, "create index complete6 on complete (a6,hostname)", NULL);
3791  switch_cache_db_create_schema(sql_manager.dbh, "create index complete7 on complete (a7,hostname)", NULL);
3792  switch_cache_db_create_schema(sql_manager.dbh, "create index complete8 on complete (a8,hostname)", NULL);
3793  switch_cache_db_create_schema(sql_manager.dbh, "create index complete9 on complete (a9,hostname)", NULL);
3794  switch_cache_db_create_schema(sql_manager.dbh, "create index complete10 on complete (a10,hostname)", NULL);
3795  switch_cache_db_create_schema(sql_manager.dbh, "create index complete11 on complete (a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,hostname)", NULL);
3796  switch_cache_db_create_schema(sql_manager.dbh, "create index nat_map_port_proto on nat (port,proto,hostname)", NULL);
3797  switch_cache_db_create_schema(sql_manager.dbh, "create index chidx1 on channels (hostname)", NULL);
3798  switch_cache_db_create_schema(sql_manager.dbh, "create index uuindex on channels (uuid, hostname)", NULL);
3799  switch_cache_db_create_schema(sql_manager.dbh, "create index uuindex2 on channels (call_uuid)", NULL);
3800  switch_cache_db_create_schema(sql_manager.dbh, "create index callsidx1 on calls (hostname)", NULL);
3801  switch_cache_db_create_schema(sql_manager.dbh, "create index eruuindex on calls (caller_uuid, hostname)", NULL);
3802  switch_cache_db_create_schema(sql_manager.dbh, "create index eeuuindex on calls (callee_uuid)", NULL);
3803  switch_cache_db_create_schema(sql_manager.dbh, "create index eeuuindex2 on calls (call_uuid)", NULL);
3804  switch_cache_db_create_schema(sql_manager.dbh, "create index regindex1 on registrations (reg_user,realm,hostname)", NULL);
3805 
3806 
3807  skip:
3808 
3809  if (sql_manager.manage) {
3810  /* Initiate switch_sql_queue_manager */
3811  switch_threadattr_create(&thd_attr, sql_manager.memory_pool);
3815  switch_thread_create(&sql_manager.db_thread, thd_attr, switch_core_sql_db_thread, NULL, sql_manager.memory_pool);
3816 
3817  /* switch_sql_queue_manager initiated, now we can bind to core_event_handler */
3818 #ifdef SWITCH_SQL_BIND_EVERY_EVENT
3820 #else
3846 #endif
3847  }
3848 
3850 
3851  return SWITCH_STATUS_SUCCESS;
3852 }
3853 
3855 {
3856  if (sql_manager.paused) {
3857  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SQL is already paused.\n");
3858  }
3859  sql_manager.paused = 1;
3860 }
3861 
3863 {
3864  if (!sql_manager.paused) {
3865  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SQL is already running.\n");
3866  }
3867  sql_manager.paused = 0;
3868 }
3869 
3870 
3872 {
3873  switch_mutex_lock(sql_manager.ctl_mutex);
3874  if (sql_manager.manage) {
3875  if (sql_manager.qm) {
3877  }
3878  } else {
3879  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL is not enabled\n");
3880  }
3881 
3882  switch_mutex_unlock(sql_manager.ctl_mutex);
3883 }
3884 
3886 {
3887 
3888  switch_mutex_lock(sql_manager.ctl_mutex);
3889  if (sql_manager.manage) {
3890  if (!sql_manager.qm) {
3891  char *dbname = runtime.odbc_dsn;
3892 
3893  if (zstr(dbname)) {
3894  dbname = runtime.dbname;
3895  if (zstr(dbname)) {
3896  dbname = "core";
3897  }
3898  }
3899 
3901  &sql_manager.qm,
3902  4,
3903  dbname,
3909 
3910  }
3912  } else {
3913  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL is not enabled\n");
3914  }
3915  switch_mutex_unlock(sql_manager.ctl_mutex);
3916 }
3917 
3919 {
3920  switch_status_t st;
3921 
3923 
3924  if (sql_manager.db_thread && sql_manager.db_thread_running) {
3925  sql_manager.db_thread_running = -1;
3926  switch_thread_join(&st, sql_manager.db_thread);
3927  }
3928 
3930 
3932  sql_close(0);
3933 }
3934 
3936 {
3937  /* return some status info suitable for the cli */
3938  switch_cache_db_handle_t *dbh = NULL;
3939  switch_bool_t locked = SWITCH_FALSE;
3940  time_t now = switch_epoch_time_now(NULL);
3941  char cleankey_str[CACHE_DB_LEN];
3942  char *pos1 = NULL;
3943  char *pos2 = NULL;
3944  int count = 0, used = 0;
3945 
3946  switch_mutex_lock(sql_manager.dbh_mutex);
3947 
3948  for (dbh = sql_manager.handle_pool; dbh; dbh = dbh->next) {
3949  char *needles[3];
3950  time_t diff = 0;
3951  int i = 0;
3952 
3953  needles[0] = "pass=\"";
3954  needles[1] = "password=";
3955  needles[2] = "password='";
3956 
3957  diff = now - dbh->last_used;
3958 
3960  switch_mutex_unlock(dbh->mutex);
3961  locked = SWITCH_FALSE;
3962  } else {
3963  locked = SWITCH_TRUE;
3964  }
3965 
3966  /* sanitize password */
3967  memset(cleankey_str, 0, sizeof(cleankey_str));
3968  for (i = 0; i < 3; i++) {
3969  if((pos1 = strstr(dbh->name, needles[i]))) {
3970  pos1 += strlen(needles[i]);
3971 
3972  if (!(pos2 = strstr(pos1, "\""))) {
3973  if (!(pos2 = strstr(pos1, "'"))) {
3974  if (!(pos2 = strstr(pos1, " "))) {
3975  pos2 = pos1 + strlen(pos1);
3976  }
3977  }
3978  }
3979  strncpy(cleankey_str, dbh->name, pos1 - dbh->name);
3980  strcpy(&cleankey_str[pos1 - dbh->name], pos2);
3981  break;
3982  }
3983  }
3984  if (i == 3) {
3985  snprintf(cleankey_str, sizeof(cleankey_str), "%s", dbh->name);
3986  }
3987 
3988  count++;
3989 
3990  if (dbh->use_count) {
3991  used++;
3992  }
3993 
3994  stream->write_function(stream, "%s\n\tType: %s\n\tLast used: %d\n\tTotal used: %ld\n\tFlags: %s, %s(%d)%s\n"
3995  "\tCreator: %s\n\tLast User: %s\n",
3996  cleankey_str,
3998  diff,
3999  dbh->total_used_count,
4000  locked ? "Locked" : "Unlocked",
4001  dbh->use_count ? "Attached" : "Detached", dbh->use_count, switch_test_flag(dbh, CDF_NONEXPIRING) ? ", Non-expiring" : "", dbh->creator, dbh->last_user);
4002  }
4003 
4004  stream->write_function(stream, "%d total. %d in use.\n", count, used);
4005 
4006  switch_mutex_unlock(sql_manager.dbh_mutex);
4007 }
4008 
4010 {
4012  return "+";
4013 
4014  return "||";
4015 }
4016 
4017 /* For Emacs:
4018  * Local Variables:
4019  * mode:c
4020  * indent-tabs-mode:t
4021  * tab-width:4
4022  * c-basic-offset:4
4023  * End:
4024  * For VIM:
4025  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
4026  */
#define SWITCH_SQL_QUEUE_LEN
#define switch_event_get_header_nil(e, h)
Definition: switch_event.h:174
switch_status_t switch_cache_db_create_schema(switch_cache_db_handle_t *dbh, char *sql, char **err)
Executes the create schema sql.
const char * switch_core_get_switchname(void)
Definition: switch_core.c:361
switch_channel_state_t switch_channel_get_state(switch_channel_t *channel)
Get the current state of a channel in the state engine.
void switch_xml_free(_In_opt_ switch_xml_t xml)
frees the memory allocated for an switch_xml structure
unsigned int switch_queue_size(switch_queue_t *queue)
Definition: switch_apr.c:1238
#define switch_strdup(ptr, s)
switch_event_types_t event_id
Definition: switch_event.h:82
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core&#39;s master pool.
Definition: switch_core.h:633
char * core_db_inner_post_trans_execute
switch_cache_db_native_handle_t native_handle
char * switch_cache_db_execute_sql2str(switch_cache_db_handle_t *dbh, char *sql, char *str, size_t len, char **err)
Executes the sql and returns the result as a string.
char name[CACHE_DB_LEN]
const char * switch_xml_attr_soft(_In_ switch_xml_t xml, _In_z_ const char *attr)
returns the value of the requested tag attribute, or "" if not found
switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_t manage)
switch_status_t switch_thread_cond_create(switch_thread_cond_t **cond, switch_memory_pool_t *pool)
Definition: switch_apr.c:373
static switch_bool_t switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:519
switch_odbc_status_t switch_odbc_handle_exec_string(switch_odbc_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err)
Definition: switch_odbc.c:412
#define SWITCH_CHANNEL_SESSION_LOG(x)
An Abstract Representation of a dialplan extension.
switch_core_db_t * handle
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:700
#define SWITCH_THREAD_FUNC
switch_odbc_status_t
Definition: switch_odbc.h:49
#define SWITCH_CHANNEL_LOG
void switch_cache_db_database_interface_flush_handles(switch_database_interface_t *database_interface)
switch_xml_t switch_xml_parse_str_dynamic(_In_z_ char *s, _In_ switch_bool_t dup)
Parses a string into a switch_xml_t, ensuring the memory will be freed with switch_xml_free.
switch_status_t switch_mutex_trylock(switch_mutex_t *lock)
Definition: switch_apr.c:318
switch_status_t(* commit)(switch_database_interface_handle_t *dih)
switch_cache_db_handle_t * event_db
static char create_interfaces_sql[]
struct switch_odbc_handle switch_odbc_handle_t
#define switch_odbc_handle_callback_exec(handle, sql, callback, pdata, err)
Execute the sql query and issue a callback for each row returned.
Definition: switch_odbc.h:93
static switch_cache_db_handle_t * create_handle(switch_cache_db_handle_type_t type)
Abstraction of an module endpoint interface This is the glue between the abstract idea of a "channel"...
uint32_t total_handles
const char * switch_channel_get_partner_uuid(switch_channel_t *channel)
#define switch_channel_set_state(channel, state)
Set the current state of a channel.
switch_status_t _switch_core_db_handle(switch_cache_db_handle_t **dbh, const char *file, const char *func, int line)
Open the default system database.
switch_status_t switch_core_check_core_db_dsn(void)
Returns error if no suitable database interface found to serve core db dsn.
static void del_handle(switch_cache_db_handle_t *dbh)
switch_bool_t switch_ivr_uuid_exists(const char *uuid)
Definition: switch_ivr.c:4026
switch_status_t(* exec_string)(switch_database_interface_handle_t *dih, const char *sql, char *resbuf, size_t len, char **err)
char * core_db_post_trans_execute
switch_cache_db_handle_type_t type
switch_cache_db_core_db_options_t core_db_options
Definition: switch_core.h:2594
int switch_odbc_handle_affected_rows(switch_odbc_handle_t *handle)
Definition: switch_odbc.c:800
switch_bool_t
Definition: switch_types.h:437
switch_status_t switch_cache_db_persistant_execute_trans_full(switch_cache_db_handle_t *dbh, char *sql, uint32_t retries, const char *pre_trans_execute, const char *post_trans_execute, const char *inner_pre_trans_execute, const char *inner_post_trans_execute)
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:733
switch_core_db_event_callback_func_t callback
#define switch_split(_data, _delim, _array)
Definition: switch_utils.h:375
void switch_odbc_handle_destroy(switch_odbc_handle_t **handlep)
Definition: switch_odbc.c:742
switch_status_t switch_threadattr_stacksize_set(switch_threadattr_t *attr, switch_size_t stacksize)
Definition: switch_apr.c:683
switch_status_t(* sql_set_auto_commit_attr)(switch_database_interface_handle_t *dih, switch_bool_t on)
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:642
#define SWITCH_EVENT_SUBCLASS_ANY
Definition: switch_event.h:128
Representation of an event.
Definition: switch_event.h:80
#define SQL_CACHE_TIMEOUT
switch_core_session_t * switch_core_session_request_xml(switch_endpoint_interface_t *endpoint_interface, switch_memory_pool_t **pool, switch_xml_t xml)
switch_status_t switch_queue_trypop(switch_queue_t *queue, void **data)
Definition: switch_apr.c:1264
static char create_tasks_sql[]
switch_odbc_status_t switch_odbc_handle_exec(switch_odbc_handle_t *handle, const char *sql, switch_odbc_statement_handle_t *rstmt, char **err)
Definition: switch_odbc.c:456
switch_core_db_t * switch_core_db_open_in_memory(const char *uri)
Open a core db (SQLite) in-memory.
void switch_sql_queue_manager_pause(switch_sql_queue_manager_t *qm, switch_bool_t flush)
static const char * switch_cache_db_type_name(switch_cache_db_handle_type_t type)
Definition: switch_core.h:2602
unsigned int switch_ci_hashfunc_default(const char *char_key, switch_ssize_t *klen)
Definition: switch_apr.c:121
void switch_sql_queue_manager_resume(switch_sql_queue_manager_t *qm)
switch_cache_db_database_interface_options_t connection_options
switch_status_t switch_cache_db_execute_sql_event_callback(switch_cache_db_handle_t *dbh, const char *sql, switch_core_db_event_callback_func_t callback, void *pdata, char **err)
int switch_core_db_close(switch_core_db_t *db)
A representation of an XML tree.
Definition: switch_xml.h:79
#define switch_cache_db_get_db_handle_dsn(_a, _b)
Definition: switch_core.h:2659
#define end_of(_s)
Definition: switch_utils.h:685
const char * switch_channel_get_variable_dup(switch_channel_t *channel, const char *varname, switch_bool_t dup, int idx)
Retrieve a variable from a given channel.
switch_status_t switch_thread_cond_wait(switch_thread_cond_t *cond, switch_mutex_t *mutex)
Definition: switch_apr.c:378
switch_status_t switch_core_del_registration(const char *user, const char *realm, const char *token)
Delete user registration.
void switch_cache_db_dismiss_db_handle(switch_cache_db_handle_t **dbh)
Returns the handle to the pool, immediately available for other threads to use.
switch_memory_pool_t * pool
char creator[CACHE_DB_LEN]
switch_memory_pool_t * memory_pool
#define SWITCH_CORE_DB_BUSY
switch_status_t switch_sql_queue_manager_stop(switch_sql_queue_manager_t *qm)
void switch_core_recovery_track(switch_core_session_t *session)
int switch_core_recovery_recover(const char *technology, const char *profile_name)
static switch_thread_t * thread
Definition: switch_log.c:486
switch_status_t switch_database_available(char *dsn)
Returns error if no suitable database interface found for a dsn.
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)
void switch_core_recovery_flush(const char *technology, const char *profile_name)
struct switch_runtime runtime
Definition: switch_core.c:86
switch_status_t switch_sql_queue_manager_push_confirm(switch_sql_queue_manager_t *qm, const char *sql, uint32_t pos, switch_bool_t dup)
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
char last_user[CACHE_DB_LEN]
switch_status_t switch_loadable_module_protect(const char *mod)
Protect module from beeing unloaded.
switch_sql_queue_manager_t * qm
static void switch_core_sqldb_start_thread(void)
switch_coredb_handle_t * core_db_dbh
Definition: switch_core.h:2569
switch_status_t(* flush)(switch_database_interface_handle_t *dih)
#define end_of_p(_s)
Definition: switch_utils.h:686
#define zstr(x)
Definition: switch_utils.h:314
int switch_core_db_step(switch_core_db_stmt_t *stmt)
switch_mutex_t * dbh_mutex
int switch_core_db_exec(switch_core_db_t *db, const char *sql, switch_core_db_callback_func_t callback, void *data, char **errmsg)
#define MIN(a, b)
switch_mutex_t * mutex
#define SWITCH_CORE_DB_OK
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
switch_status_t switch_cache_db_persistant_execute(switch_cache_db_handle_t *dbh, const char *sql, uint32_t retries)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
static void add_handle(switch_cache_db_handle_t *dbh, const char *db_str, const char *db_callsite_str, const char *thread_str)
struct switch_cache_db_handle * next
#define UNPROTECT_INTERFACE(_it)
#define switch_clear_flag(obj, flag)
Clear a flag on an arbitrary object while locked.
Definition: switch_utils.h:724
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
int switch_sql_queue_manager_size(switch_sql_queue_manager_t *qm, uint32_t index)
void switch_cache_db_flush_handles(void)
switch_status_t _switch_cache_db_get_db_handle_dsn(switch_cache_db_handle_t **dbh, const char *dsn, const char *file, const char *func, int line)
static char recovery_sql[]
static char * parse_presence_data_cols(switch_event_t *event)
switch_status_t switch_event_bind(const char *id, switch_event_types_t event, const char *subclass_name, switch_event_callback_t callback, void *user_data)
Bind an event callback to a specific event.
switch_dbtype_t odbc_dbtype
void switch_core_sqldb_stop(void)
switch_xml_t next
Definition: switch_xml.h:91
switch_database_interface_t * switch_loadable_module_get_database_interface(const char *name, const char *modname)
Retrieve the database interface by it&#39;s registered name.
#define new_sql_a()
switch_cache_db_handle_type_t switch_cache_db_get_type(switch_cache_db_handle_t *dbh)
if((uint32_t)(unpack->cur - unpack->buf) > unpack->buflen)
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:998
#define SQL_REG_TIMEOUT
switch_channel_t * channel
static switch_thread_data_t * new_job(switch_sql_queue_manager_t *qm, const char *sql, switch_core_db_callback_func_t callback, switch_core_db_err_callback_func_t err_callback, switch_core_db_event_callback_func_t event_callback, switch_core_db_err_callback_func_t event_err_callback, void *pdata)
static uint32_t do_trans(switch_sql_queue_manager_t *qm)
#define MAX_SQL
char * switch_core_get_uuid(void)
Retrieve the unique identifier from the core.
Definition: switch_core.c:495
switch_core_db_err_callback_func_t event_err_callback
static char create_channels_sql[]
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
int switch_cache_db_affected_rows(switch_cache_db_handle_t *dbh)
Get the affected rows of the last performed query.
intptr_t switch_ssize_t
switch_cache_db_handle_type_t
Definition: switch_core.h:2562
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:684
#define switch_channel_get_variable(_c, _v)
int index
Definition: switch_cJSON.h:160
#define SWITCH_THREAD_STACKSIZE
Definition: switch_types.h:584
#define new_sql()
int switch_core_db_load_extension(switch_core_db_t *db, const char *extension)
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:885
static char create_nat_sql[]
switch_thread_start_t func
Definition: switch_core.h:67
switch_status_t(* affected_rows)(switch_database_interface_handle_t *dih, int *affected_rows)
switch_core_db_err_callback_func_t err_callback
#define CACHE_DB_LEN
Definition: switch_core.h:2555
switch_memory_pool_t * pool
static void *SWITCH_THREAD_FUNC switch_user_sql_thread(switch_thread_t *thread, void *obj)
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:293
void switch_core_sqldb_resume(void)
switch_sql_queue_manager_t * qm
switch_status_t switch_thread_join(switch_status_t *retval, switch_thread_t *thd)
Definition: switch_apr.c:1379
switch_bool_t manage
switch_bool_t switch_odbc_available(void)
Definition: switch_odbc.c:809
void switch_core_sql_exec(const char *sql)
void switch_sql_queue_manager_execute_sql_event_callback_err(switch_sql_queue_manager_t *qm, const char *sql, switch_core_db_event_callback_func_t callback, switch_core_db_err_callback_func_t err_callback, void *pdata)
char * switch_snprintfv(char *zBuf, int n, const char *zFormat,...)
void switch_channel_set_caller_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension)
Assign a caller extension to a given channel.
int switch_cache_db_load_extension(switch_cache_db_handle_t *dbh, const char *extension)
load an external extension to db
uintptr_t switch_size_t
uint32_t db_handle_timeout
void switch_caller_extension_add_application(_In_ switch_core_session_t *session, _In_ switch_caller_extension_t *caller_extension, _In_z_ const char *application_name, _In_z_ const char *extra_data)
Add an application (instruction) to the given extension.
static char create_calls_sql[]
int(* switch_core_db_callback_func_t)(void *pArg, int argc, char **argv, char **columnNames)
pthread_t switch_thread_id_t
Definition: switch_apr.h:51
void switch_cond_next(void)
Definition: switch_time.c:658
switch_status_t switch_cache_db_execute_sql_event_callback_err(switch_cache_db_handle_t *dbh, const char *sql, switch_core_db_event_callback_func_t callback, switch_core_db_err_callback_func_t err_callback, void *pdata, char **err)
static char detailed_calls_sql[]
int paused
void switch_cache_db_status(switch_stream_handle_t *stream)
Provides some feedback as to the status of the db connection pool.
#define SWITCH_STANDARD_STREAM(s)
switch_odbc_handle_t * odbc_dbh
Definition: switch_core.h:2570
switch_channel_callstate_t
char * switch_copy_string(_Out_z_cap_(dst_size) char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size)
switch_cache_db_odbc_options_t odbc_options
Definition: switch_core.h:2595
switch_database_interface_handle_t * database_interface_dbh
Definition: switch_core.h:2571
switch_caller_extension_t * switch_caller_extension_new(_In_ switch_core_session_t *session, _In_z_ const char *extension_name, _In_z_ const char *extension_number)
Create a new extension with desired parameters.
static int32_t running
switch_cache_db_handle_t * handle_pool
char * switch_core_session_get_uuid(_In_ switch_core_session_t *session)
Retrieve the unique identifier from a session.
switch_cache_db_handle_t * dbh
switch_status_t(* handle_destroy)(switch_database_interface_handle_t **dih)
#define switch_core_db_handle(_a)
Definition: switch_core.h:2729
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:993
struct fspr_thread_mutex_t switch_mutex_t
Definition: switch_apr.h:314
void switch_core_sqldb_pause(void)
switch_memory_pool_t * pool
switch_status_t switch_thread_cond_signal(switch_thread_cond_t *cond)
Definition: switch_apr.c:394
static int switch_channel_var_true(switch_channel_t *channel, const char *variable)
void switch_cache_db_release_db_handle(switch_cache_db_handle_t **dbh)
Returns the handle to the pool, handle is NOT available to other threads until the allocating thread ...
void switch_core_recovery_untrack(switch_core_session_t *session, switch_bool_t force)
switch_core_recover_callback_t recover_callback
switch_channel_state_t
Channel States (these are the defaults, CS_SOFT_EXECUTE, CS_EXCHANGE_MEDIA, and CS_CONSUME_MEDIA are ...
static switch_cache_db_handle_t * get_handle(const char *db_str, const char *user_str, const char *thread_str)
uint32_t total_used_handles
switch_stream_handle_write_function_t write_function
switch_status_t
Common return values.
static char basic_calls_sql[]
char * switch_string_replace(const char *string, const char *search, const char *replace)
static switch_status_t switch_cache_db_execute_sql_real(switch_cache_db_handle_t *dbh, const char *sql, char **err)
#define switch_xml_toxml_nolock(xml, prn_header)
Definition: switch_xml.h:225
switch_status_t switch_sql_queue_manager_init_name(const char *name, switch_sql_queue_manager_t **qmp, uint32_t numq, const char *dsn, uint32_t max_trans, const char *pre_trans_execute, const char *post_trans_execute, const char *inner_pre_trans_execute, const char *inner_post_trans_execute)
switch_endpoint_interface_t * switch_loadable_module_get_endpoint_interface(const char *name)
Retrieve the endpoint interface by it&#39;s registered name.
void switch_sql_queue_manager_execute_sql_callback(switch_sql_queue_manager_t *qm, const char *sql, switch_core_db_callback_func_t callback, void *pdata)
switch_status_t _switch_cache_db_get_db_handle_dsn_ex(switch_cache_db_handle_t **dbh, const char *dsn, switch_bool_t make_module_no_unloadable, const char *file, const char *func, int line)
static void *SWITCH_THREAD_FUNC switch_core_sql_db_thread(switch_thread_t *thread, void *obj)
const char * switch_core_get_hostname(void)
Definition: switch_core.c:356
switch_status_t switch_core_expire_registration(int force)
Expire user registrations.
static int helper_callback(void *pArg, int argc, char **argv, char **columnNames)
struct sqlite3 switch_core_db_t
switch_status_t switch_queue_interrupt_all(switch_queue_t *queue)
Definition: switch_apr.c:1269
static struct @4 sql_manager
switch_odbc_status_t switch_odbc_handle_connect(switch_odbc_handle_t *handle)
Definition: switch_odbc.c:343
Main Library Header.
static int recover_callback(void *pArg, int argc, char **argv, char **columnNames)
switch_core_db_callback_func_t callback
int(* switch_core_db_event_callback_func_t)(void *pArg, switch_event_t *event)
Definition: switch_core.h:2553
int(* switch_core_db_err_callback_func_t)(void *pArg, const char *errmsg)
switch_cache_db_database_interface_options_t database_interface_options
Definition: switch_core.h:2596
int(* switch_core_recover_callback_t)(switch_core_session_t *session)
#define SWITCH_DECLARE(type)
const char * filename
struct fspr_thread_cond_t switch_thread_cond_t
Definition: switch_apr.h:463
uint32_t max_db_handles
#define switch_event_get_header(_e, _h)
Definition: switch_event.h:172
switch_odbc_status_t switch_odbc_SQLEndTran(switch_odbc_handle_t *handle, switch_bool_t commit)
Definition: switch_odbc.c:835
#define switch_channel_set_flag(_c, _f)
switch_xml_t switch_xml_child(_In_ switch_xml_t xml, _In_z_ const char *name)
returns the first child tag (one level deeper) with the given name or NULL \ if not found ...
switch_bool_t switch_cache_db_test_reactive(switch_cache_db_handle_t *dbh, const char *test_sql, const char *drop_sql, const char *reactive_sql)
Performs test_sql and if it fails performs drop_sql and reactive_sql.
#define SWITCH_CORE_DB_ABORT
static char create_registrations_sql[]
static int qm_wake(switch_sql_queue_manager_t *qm)
#define switch_set_string(_dst, _src)
Definition: switch_utils.h:734
switch_thread_cond_t * cond
switch_status_t switch_queue_trypush(switch_queue_t *queue, void *data)
Definition: switch_apr.c:1279
switch_status_t switch_event_create_array_pair(switch_event_t **event, char **names, char **vals, int len)
char * core_db_pre_trans_execute
static void switch_core_sqldb_stop_thread(void)
void switch_core_db_free(char *z)
struct sqlite3_stmt switch_core_db_stmt_t
time_t switch_epoch_time_now(time_t *t)
Get the current epoch time.
Definition: switch_time.c:322
switch_status_t switch_sql_queue_manager_destroy(switch_sql_queue_manager_t **qmp)
#define SWITCH_CORE_DB_ROW
switch_core_recover_callback_t switch_core_get_secondary_recover_callback(const char *key)
char * key
Definition: switch_msrp.c:64
switch_status_t switch_sql_queue_manager_start(switch_sql_queue_manager_t *qm)
#define SWITCH_MAX_TRANS
Definition: switch_types.h:238
switch_status_t switch_queue_push(switch_queue_t *queue, void *data)
Definition: switch_apr.c:1253
switch_status_t switch_cache_db_execute_sql_callback(switch_cache_db_handle_t *dbh, const char *sql, switch_core_db_callback_func_t callback, void *pdata, char **err)
Executes the sql and uses callback for row-by-row processing.
switch_bool_t switch_cache_db_test_reactive_ex(switch_cache_db_handle_t *dbh, const char *test_sql, const char *drop_sql, const char *reactive_sql, const char *row_size_limited_reactive_sql)
switch_status_t switch_event_unbind_callback(switch_event_callback_t callback)
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
#define database_interface_handle_exec(database_interface, dih, sql, err)
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.
const char * switch_stristr(const char *instr, const char *str)
int switch_core_db_changes(switch_core_db_t *db)
switch_status_t switch_threadattr_create(switch_threadattr_t **new_attr, switch_memory_pool_t *pool)
Definition: switch_apr.c:665
switch_status_t switch_thread_create(switch_thread_t **new_thread, switch_threadattr_t *attr, switch_thread_start_t func, void *data, switch_memory_pool_t *cont)
Definition: switch_apr.c:698
#define PROTECT_INTERFACE(_it)
switch_endpoint_interface_t * endpoint_interface
switch_status_t switch_sql_queue_manager_push(switch_sql_queue_manager_t *qm, const char *sql, uint32_t pos, switch_bool_t dup)
int count
Definition: switch_cJSON.h:204
struct fspr_pool_t switch_memory_pool_t
int switch_core_db_column_count(switch_core_db_stmt_t *pStmt)
switch_status_t switch_queue_create(switch_queue_t **queue, unsigned int queue_capacity, switch_memory_pool_t *pool)
Definition: switch_apr.c:1233
static uint32_t qm_ttl(switch_sql_queue_manager_t *qm)
switch_thread_id_t switch_thread_self(void)
Definition: switch_apr.c:102
void switch_event_destroy(switch_event_t **event)
Destroy an event.
char * switch_sql_concat(void)
switch_mutex_t * ctl_mutex
switch_status_t switch_cache_db_execute_sql(switch_cache_db_handle_t *dbh, char *sql, char **err)
Executes the sql.
switch_core_db_event_callback_func_t event_callback
const unsigned char * switch_core_db_column_text(switch_core_db_stmt_t *stmt, int iCol)
static char create_complete_sql[]
void switch_sql_queue_manager_execute_sql_event_callback(switch_sql_queue_manager_t *qm, const char *sql, switch_core_db_event_callback_func_t callback, void *pdata)
switch_bool_t in_memory
static void core_event_handler(switch_event_t *event)
char * core_db_inner_pre_trans_execute
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
#define switch_assert(expr)
struct fspr_thread_t switch_thread_t
Definition: switch_apr.h:941
void switch_sql_queue_manager_execute_sql_callback_err(switch_sql_queue_manager_t *qm, const char *sql, switch_core_db_callback_func_t callback, switch_core_db_err_callback_func_t err_callback, void *pdata)
switch_odbc_handle_t * switch_odbc_handle_new(const char *dsn, const char *username, const char *password)
Definition: switch_odbc.c:72
static void sql_close(time_t prune)
switch_database_interface_t * database_interface
Definition: switch_core.h:2589
switch_thread_t * db_thread
switch_status_t switch_ivr_generate_xml_cdr(switch_core_session_t *session, switch_xml_t *xml_cdr)
Generate an XML CDR report.
Definition: switch_ivr.c:2862
switch_core_db_t * switch_core_db_open_file(const char *filename)
Open a core db (SQLite) file.
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
switch_status_t(* handle_new)(switch_cache_db_database_interface_options_t database_interface_options, switch_database_interface_handle_t **dih)
#define database_interface_handle_callback_exec(database_interface, dih, sql, callback, pdata, err)
Abstract interface to a database module.
SWITCH_BEGIN_EXTERN_C char * switch_mprintf(const char *zFormat,...)
switch_status_t switch_cache_db_execute_sql_callback_err(switch_cache_db_handle_t *dbh, const char *sql, switch_core_db_callback_func_t callback, switch_core_db_err_callback_func_t err_callback, void *pdata, char **err)
Executes the sql and uses callback for row-by-row processing.
static void *SWITCH_THREAD_FUNC sql_in_thread(switch_thread_t *thread, void *obj)
memset(buf, 0, buflen)
void switch_core_media_recover_session(switch_core_session_t *session)
switch_odbc_status_t switch_odbc_SQLSetAutoCommitAttr(switch_odbc_handle_t *handle, switch_bool_t on)
Definition: switch_odbc.c:818
static char create_row_size_limited_channels_sql[]
int switch_core_db_prepare(switch_core_db_t *db, const char *zSql, int nBytes, switch_core_db_stmt_t **ppStmt, const char **pzTail)
static void do_flush(switch_sql_queue_manager_t *qm, int i, switch_cache_db_handle_t *dbh)
static void destroy_handle(switch_cache_db_handle_t **dbh)
static char create_alias_sql[]
switch_status_t switch_core_add_registration(const char *user, const char *realm, const char *token, const char *url, uint32_t expires, const char *network_ip, const char *network_port, const char *network_proto, const char *metadata)
Add user registration.
switch_status_t _switch_cache_db_get_db_handle(switch_cache_db_handle_t **dbh, switch_cache_db_handle_type_t type, switch_cache_db_connection_options_t *connection_options, const char *file, const char *func, int line)
Gets a new cached handle from the pool, potentially creating a new connection. The connection is boun...
switch_loadable_module_interface_t * parent
switch_status_t switch_core_session_thread_launch(_In_ switch_core_session_t *session)
Launch the session thread (state machine) on a given session.
switch_status_t switch_thread_pool_launch_thread(switch_thread_data_t **tdp)
int db_thread_running
static switch_status_t switch_cache_db_execute_sql_chunked(switch_cache_db_handle_t *dbh, char *sql, uint32_t chunk_size, char **err)
switch_cache_db_handle_type_t switch_core_dbtype(void)
switch_status_t switch_threadattr_priority_set(switch_threadattr_t *attr, switch_thread_priority_t priority)
Definition: switch_apr.c:688