35#include <mysql/mysql.h>
36#include <mysql/errmsg.h>
49#define RES_CONFIG_MYSQL_CONF "res_config_mysql.conf"
50#define RES_CONFIG_MYSQL_CONF_OLD "res_mysql.conf"
54#define ESCAPE_STRING(buf, var) \
56 struct ast_str *semi = ast_str_thread_get(&scratch2_buf, strlen(var) * 3 + 1); \
57 const char *chunk = var; \
58 ast_str_reset(semi); \
59 for (; *chunk; chunk++) { \
60 if (strchr(";^", *chunk)) { \
61 ast_str_append(&semi, 0, "^%02hhX", *chunk); \
63 ast_str_append(&semi, 0, "%c", *chunk); \
66 if (ast_str_strlen(semi) * 2 + 1 > ast_str_size(buf)) { \
67 ast_str_make_space(&(buf), ast_str_strlen(semi) * 2 + 1); \
69 mysql_real_escape_string(&dbh->handle, ast_str_buffer(buf), ast_str_buffer(semi), ast_str_strlen(semi)); \
125static int require_mysql(
const char *database,
const char *tablename, va_list ap);
138 if ((ptr = strchr(database,
'/'))) {
144 strncpy(whichdb, database, ptr - database);
145 whichdb[ptr - database] =
'\0';
153 if (!strcmp(cur->unique_name, whichdb)) {
162#define release_database(a) ast_mutex_unlock(&(a)->lock)
181 char *fname, *ftype, *flen, *fdflt, *fnull;
192 if (!strcasecmp(
table->name, tablename)) {
210 ast_log(
LOG_ERROR,
"Failed to query database '%s', table '%s' columns: %s\n", database, tablename, mysql_error(&dbh->handle));
222 strcpy(
table->name, tablename);
223 table->database = dbh;
227 if ((
result = mysql_store_result(&dbh->handle))) {
228 while ((row = mysql_fetch_row(
result))) {
233 ast_verb(4,
"Found column '%s' of type '%s'\n", fname, ftype);
239 if (!(column =
ast_calloc(1,
sizeof(*column) + strlen(fname) + strlen(ftype) + strlen(fdflt) + 3))) {
240 ast_log(
LOG_ERROR,
"Unable to allocate column element %s for %s\n", fname, tablename);
247 if ((flen = strchr(ftype,
'('))) {
248 sscanf(flen,
"(%30d)", &column->
len);
254 column->
name = (
char *)column +
sizeof(*column);
255 column->
type = (
char *)column +
sizeof(*column) + strlen(fname) + 1;
256 column->
dflt = (
char *)column +
sizeof(*column) + strlen(fname) + 1 + strlen(ftype) + 1;
257 strcpy(column->
name, fname);
258 strcpy(column->
type, ftype);
259 strcpy(column->
dflt, fdflt);
260 column->
null = (strcmp(fnull,
"YES") == 0 ? 1 : 0);
263 mysql_free_result(
result);
285 if (strcmp(column->
name, colname) == 0) {
296 for (; *chunk; chunk++) {
297 if (*chunk ==
'^' && strchr(
"0123456789ABCDEFabcdef", chunk[1]) && strchr(
"0123456789ABCDEFabcdef", chunk[2])) {
298 sscanf(chunk + 1,
"%02hhX", chunk);
299 memmove(chunk + 1, chunk + 3, strlen(chunk + 3) + 1);
305#define IS_SQL_LIKE_CLAUSE(x) ((x) && ast_ends_with(x, " LIKE"))
327 ast_log(
LOG_WARNING,
"MySQL RealTime: Invalid database specified: %s (check res_mysql.conf)\n", database);
339 ast_log(
LOG_WARNING,
"MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
353 if (!strchr(field->
name,
' ')) {
364 while ((field = field->
next)) {
366 if (!strchr(field->
name,
' ')) {
382 ast_log(
LOG_WARNING,
"MySQL RealTime: Failed to query database: %s\n", mysql_error(&dbh->handle));
387 if ((
result = mysql_store_result(&dbh->handle))) {
388 numFields = mysql_num_fields(
result);
389 fields = mysql_fetch_fields(
result);
391 while ((row = mysql_fetch_row(
result))) {
392 for (i = 0; i < numFields; i++) {
394 if (row[i] ==
NULL) {
399 for (stringp = row[i], chunk =
strsep(&stringp,
";"); chunk; chunk =
strsep(&stringp,
";")) {
411 ast_debug(1,
"MySQL RealTime: Could not find any rows in table %s.\n",
table);
415 mysql_free_result(
result);
429 const char *initfield =
NULL;
440 ast_log(
LOG_WARNING,
"MySQL RealTime: Invalid database specified: '%s' (check res_mysql.conf)\n", database);
459 ast_log(
LOG_WARNING,
"MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
466 if ((op = strchr(initfield,
' '))) {
480 if (!strchr(field->
name,
' ')) {
491 while ((field = field->
next)) {
493 if (!strchr(field->
name,
' ')) {
513 ast_log(
LOG_WARNING,
"MySQL RealTime: Failed to query database: %s\n", mysql_error(&dbh->handle));
519 if ((
result = mysql_store_result(&dbh->handle))) {
520 numFields = mysql_num_fields(
result);
521 fields = mysql_fetch_fields(
result);
523 while ((row = mysql_fetch_row(
result))) {
529 for (i = 0; i < numFields; i++) {
532 for (stringp = row[i], chunk =
strsep(&stringp,
";"); chunk; chunk =
strsep(&stringp,
";")) {
534 if (initfield && !strcmp(initfield, fields[i].
name)) {
545 ast_debug(1,
"MySQL RealTime: Could not find any rows in table %s.\n",
table);
549 mysql_free_result(
result);
554static int update_mysql(
const char *database,
const char *tablename,
const char *keyfield,
const char *lookup,
const struct ast_variable *rt_fields)
564 ast_log(
LOG_WARNING,
"MySQL RealTime: Invalid database specified: '%s' (check res_mysql.conf)\n", database);
581 ast_log(
LOG_ERROR,
"MySQL RealTime: Updating on column '%s', but that column does not exist within the table '%s' (db '%s')!\n", keyfield, tablename, database);
589 ast_log(
LOG_WARNING,
"MySQL RealTime: Realtime update requires at least 1 parameter and 1 value to update.\n");
597 ast_log(
LOG_ERROR,
"MySQL RealTime: Updating column '%s', but that column does not exist within the table '%s' (first pair MUST exist)!\n", field->
name, tablename);
616 while ((field = field->
next)) {
619 ast_log(
LOG_WARNING,
"Attempted to update column '%s' in table '%s', but column does not exist!\n", field->
name, tablename);
634 ast_log(
LOG_WARNING,
"MySQL RealTime: Failed to update database: %s\n", mysql_error(&dbh->handle));
640 numrows = mysql_affected_rows(&dbh->handle);
644 ast_debug(1,
"MySQL RealTime: Updated %" PRIu64
" rows on table: %s\n", numrows, tablename);
682 if (!sql || !
buf || !where) {
699 for (field = lookup_fields; field; field = field->
next) {
701 ast_log(
LOG_ERROR,
"Updating on column '%s', but that column does not exist within the table '%s'!\n", field->
name, tablename);
712 for (field = update_fields; field; field = field->
next) {
715 ast_log(
LOG_WARNING,
"Attempted to update column '%s' in table '%s', but column does not exist!\n", field->
name, tablename);
732 ast_log(
LOG_WARNING,
"MySQL RealTime: Failed to update database: %s\n", mysql_error(&dbh->handle));
738 numrows = mysql_affected_rows(&dbh->handle);
741 ast_debug(1,
"MySQL RealTime: Updated %" PRIu64
" rows on table: %s\n", numrows, tablename);
761 ast_log(
LOG_WARNING,
"MySQL RealTime: Invalid database specified: '%s' (check res_mysql.conf)\n", database);
772 ast_log(
LOG_WARNING,
"MySQL RealTime: Realtime storage requires at least 1 parameter and 1 value to search on.\n");
787 while ((field = field->
next)) {
798 ast_log(
LOG_WARNING,
"MySQL RealTime: Failed to insert into database: %s\n", mysql_error(&dbh->handle));
805 ast_debug(1,
"MySQL RealTime: row inserted on table: %s\n",
table);
819 ast_log(
LOG_WARNING,
"MySQL RealTime: Invalid database specified: '%s' (check res_mysql.conf)\n", database);
833 ast_log(
LOG_WARNING,
"MySQL RealTime: Realtime destroying requires at least 1 parameter and 1 value to search on.\n");
848 for (field = rt_fields; field; field = field->
next) {
857 ast_log(
LOG_WARNING,
"MySQL RealTime: Failed to delete from database: %s\n", mysql_error(&dbh->handle));
862 numrows = mysql_affected_rows(&dbh->handle);
865 ast_debug(1,
"MySQL RealTime: Deleted %" PRIu64
" rows on table: %s\n", numrows,
table);
886 int last_cat_metric = 0;
896 ast_log(
LOG_WARNING,
"MySQL RealTime: Invalid database specified: '%s' (check res_mysql.conf)\n", database);
900 ast_str_set(&sql, 0,
"SELECT category, var_name, var_val, cat_metric FROM %s WHERE filename='%s' and commented=0 ORDER BY filename, category, cat_metric desc, var_metric asc, var_name, var_val, id",
table,
file);
910 ast_log(
LOG_WARNING,
"MySQL RealTime: Failed to query database. Check debug for more info.\n");
912 ast_debug(1,
"MySQL RealTime: Query Failed because: %s\n", mysql_error(&dbh->handle));
917 if ((
result = mysql_store_result(&dbh->handle))) {
918 num_rows = mysql_num_rows(
result);
919 ast_debug(1,
"MySQL RealTime: Found %" PRIu64
" rows.\n", num_rows);
924 while ((row = mysql_fetch_row(
result))) {
925 if (!strcmp(row[1],
"#include")) {
927 mysql_free_result(
result);
934 if (strcmp(
last, row[0]) || last_cat_metric != atoi(row[3])) {
939 strcpy(
last, row[0]);
940 last_cat_metric = atoi(row[3]);
951 mysql_free_result(
result);
962 if (strcmp(cur->
name, tablename) == 0) {
983 ast_log(
LOG_WARNING,
"Table %s not found in database. This table should exist if you're using realtime.\n", tablename);
987 while ((elm = va_arg(ap,
char *))) {
989 size = va_arg(ap,
int);
992 if (strcmp(column->
name, elm) == 0) {
994 if (strncmp(column->
type,
"char", 4) == 0 || strncmp(column->
type,
"varchar", 7) == 0) {
995 if ((size > column->
len) && column->
len != -1) {
996 ast_log(
LOG_WARNING,
"Realtime table %s@%s: Column '%s' should be at least %d long, but is only %d long.\n",
database, tablename, column->
name, size, column->
len);
1001 ast_log(
LOG_WARNING,
"Realtime table %s@%s: column '%s' cannot be type '%s' (need %s)\n",
1006 }
else if (strncasecmp(column->
type,
"tinyint", 1) == 0) {
1008 ast_log(
LOG_WARNING,
"Realtime table %s@%s: column '%s' may not be large enough for " \
1009 "the required data length: %d (detected stringtype)\n", \
1013 }
else if (strncasecmp(column->
type,
"smallint", 1) == 0) {
1015 ast_log(
LOG_WARNING,
"Realtime table %s@%s: column '%s' may not be large enough for " \
1016 "the required data length: %d (detected stringtype)\n", \
1020 }
else if (strncasecmp(column->
type,
"mediumint", 1) == 0) {
1024 ast_log(
LOG_WARNING,
"Realtime table %s@%s: column '%s' may not be large enough for " \
1025 "the required data length: %d (detected stringtype)\n", \
1029 }
else if (strncasecmp(column->
type,
"int", 1) == 0) {
1034 ast_log(
LOG_WARNING,
"Realtime table %s@%s: column '%s' may not be large enough for " \
1035 "the required data length: %d (detected stringtype)\n", \
1039 }
else if (strncasecmp(column->
type,
"bigint", 1) == 0) {
1045 ast_log(
LOG_WARNING,
"Realtime table %s@%s: column '%s' may not be large enough for " \
1046 "the required data length: %d (detected stringtype)\n", \
1053 ast_log(
LOG_WARNING,
"Realtime table %s@%s: column '%s' cannot be type '%s' (need %s)\n",
1057 "to get a life, rather than writing silly error messages");
1059 }
else if (strncasecmp(column->
type,
"tinyint", 1) == 0) {
1061 ast_log(
LOG_WARNING,
"Realtime table %s@%s: column '%s' may not be large enough for " \
1062 "the required data length: %d (detected stringtype)\n", \
1066 }
else if (strncasecmp(column->
type,
"smallint", 1) == 0) {
1068 ast_log(
LOG_WARNING,
"Realtime table %s@%s: column '%s' may not be large enough for " \
1069 "the required data length: %d (detected stringtype)\n", \
1073 }
else if (strncasecmp(column->
type,
"mediumint", 1) == 0) {
1077 ast_log(
LOG_WARNING,
"Realtime table %s@%s: column '%s' may not be large enough for " \
1078 "the required data length: %d (detected stringtype)\n", \
1082 }
else if (strncasecmp(column->
type,
"int", 1) == 0) {
1087 ast_log(
LOG_WARNING,
"Realtime table %s@%s: column '%s' may not be large enough for " \
1088 "the required data length: %d (detected stringtype)\n", \
1092 }
else if (strncasecmp(column->
type,
"bigint", 1) == 0) {
1098 ast_log(
LOG_WARNING,
"Realtime table %s@%s: column '%s' may not be large enough for " \
1099 "the required data length: %d (detected stringtype)\n", \
1104 }
else if (strncmp(column->
type,
"float", 5) == 0) {
1109 }
else if (strncmp(column->
type,
"datetime", 8) == 0 || strncmp(column->
type,
"timestamp", 9) == 0) {
1114 }
else if (strncmp(column->
type,
"date", 4) == 0) {
1128 ast_log(
LOG_WARNING,
"Table %s requires a column '%s' of size '%d', but no such column exists.\n", tablename, elm, size);
1154 ast_verb(2,
"MySQL RealTime driver loaded.\n");
1166 ast_verb(2,
"MySQL RealTime unloaded.\n");
1170 mysql_close(&cur->handle);
1189 ast_verb(2,
"MySQL RealTime reloaded.\n");
1217 if (!strcmp(cur->unique_name, catg)) {
1223 if (!(cur =
ast_calloc(1,
sizeof(*cur) + strlen(catg) + 1))) {
1228 strcpy(cur->unique_name, catg);
1247 ast_log(
LOG_WARNING,
"MySQL RealTime: No database user found, using 'asterisk' as default.\n");
1253 ast_log(
LOG_WARNING,
"MySQL RealTime: No database password found, using 'asterisk' as default.\n");
1259 ast_log(
LOG_WARNING,
"MySQL RealTime: No database host found, using localhost via socket.\n");
1265 ast_log(
LOG_WARNING,
"MySQL RealTime: No database name found, using 'asterisk' as default.\n");
1271 ast_log(
LOG_WARNING,
"MySQL RealTime: No database port found, using 3306 as default.\n");
1274 conn->port = atoi(s);
1278 char *paths[3] = {
"/tmp/mysql.sock",
"/var/lib/mysql/mysql.sock",
"/var/run/mysqld/mysqld.sock" };
1281 for (i = 0; i < 3; i++) {
1282 if (!stat(paths[i], &st)) {
1283 ast_log(
LOG_WARNING,
"MySQL RealTime: No database socket found, using '%s' as default.\n", paths[i]);
1288 ast_log(
LOG_WARNING,
"MySQL RealTime: No database socket found (and unable to detect a suitable path).\n");
1300 ast_log(
LOG_WARNING,
"MySQL realtime: no requirements setting found, using 'warn' as default.\n");
1302 }
else if (!strcasecmp(s,
"createclose")) {
1304 }
else if (!strcasecmp(s,
"createchar")) {
1306 }
else if (!strcasecmp(s,
"warn")) {
1309 ast_log(
LOG_WARNING,
"MySQL realtime: unrecognized requirements setting '%s', using 'warn'\n", s);
1318 ast_debug(1,
"MySQL RealTime database name: %s\n",
conn->name);
1322 ast_debug(1,
"MySQL RealTime charset: %s\n",
conn->charset);
1329#ifdef MYSQL_OPT_RECONNECT
1330 my_bool trueval = 1;
1337 if (!mysql_init(&
conn->handle)) {
1338 ast_log(
LOG_WARNING,
"MySQL RealTime: Insufficient memory to allocate MySQL resource.\n");
1339 conn->connected = 0;
1342 if(strlen(
conn->charset) > 2){
1343 char set_names[255];
1344 char statement[512];
1345 snprintf(set_names,
sizeof(set_names),
"SET NAMES %s",
conn->charset);
1346 mysql_real_escape_string(&
conn->handle, statement, set_names,
sizeof(set_names));
1347 mysql_options(&
conn->handle, MYSQL_INIT_COMMAND, set_names);
1348 mysql_options(&
conn->handle, MYSQL_SET_CHARSET_NAME,
conn->charset);
1352#ifdef MYSQL_OPT_RECONNECT
1355 mysql_options(&
conn->handle, MYSQL_OPT_RECONNECT, &trueval);
1357 ast_debug(1,
"MySQL RealTime: Successfully connected to database.\n");
1358 conn->connected = 1;
1363 ast_debug(1,
"MySQL RealTime: Cannot Connect (%d): %s\n", mysql_errno(&
conn->handle), mysql_error(&
conn->handle));
1364 conn->connected = 0;
1365 conn->connect_time = 0;
1371 if (mysql_ping(&
conn->handle) != 0 && (usleep(1) + 2 > 0) && mysql_ping(&
conn->handle) != 0) {
1372 conn->connected = 0;
1373 conn->connect_time = 0;
1374 ast_log(
LOG_ERROR,
"MySQL RealTime: Ping failed (%d). Trying an explicit reconnect.\n", mysql_errno(&
conn->handle));
1375 ast_debug(1,
"MySQL RealTime: Server Error (%d): %s\n", mysql_errno(&
conn->handle), mysql_error(&
conn->handle));
1376 goto reconnect_tryagain;
1379 if (!
conn->connected) {
1380 conn->connected = 1;
1384 if (mysql_select_db(&
conn->handle,
conn->name) != 0) {
1385 ast_log(
LOG_WARNING,
"MySQL RealTime: Unable to select database: %s. Still Connected (%u) - %s.\n",
conn->name, mysql_errno(&
conn->handle), mysql_error(&
conn->handle));
1389 ast_debug(1,
"MySQL RealTime: Connection okay.\n");
1402 e->
command =
"realtime mysql cache";
1404 "Usage: realtime mysql cache [<database> <table>]\n"
1405 " Shows table cache for the MySQL RealTime driver\n";
1408 if (
a->argc < 4 ||
a->argc > 5) {
1411 l = strlen(
a->word);
1416 if (!strcasecmp(
a->argv[3], cur->
database->unique_name) && !strncasecmp(
a->word, cur->
name, l) && ++which >
a->n) {
1426 if (!strncasecmp(
a->word, cur->unique_name, l) && ++which >
a->n) {
1443 }
else if (
a->argc == 4) {
1448 if (!strcasecmp(cur->
database->unique_name,
a->argv[3])) {
1455 ast_cli(
a->fd,
"No tables cached within %s database\n",
a->argv[3]);
1457 }
else if (
a->argc == 5) {
1461 ast_cli(
a->fd,
"Columns for Table Cache '%s':\n",
a->argv[3]);
1462 ast_cli(
a->fd,
"%-20.20s %-20.20s %-3.3s\n",
"Name",
"Type",
"Len");
1468 ast_cli(
a->fd,
"No such table '%s'\n",
a->argv[3]);
1476 char status[256], status2[100] =
"",
type[20];
1478 int ctime = 0, found = 0;
1480 int l = 0, which = 0;
1484 e->
command =
"realtime mysql status";
1486 "Usage: realtime mysql status [<database>]\n"
1487 " Shows connection information for the MySQL RealTime driver\n";
1493 if (!strncasecmp(
a->word, cur->unique_name, l) && ++which >
a->n) {
1508 if (
a->argc == 3 || (
a->argc == 4 && !strcasecmp(
a->argv[3], cur->unique_name))) {
1512 snprintf(
type,
sizeof(
type),
"connected to");
1513 ctime = time(
NULL) - cur->connect_time;
1515 snprintf(
type,
sizeof(
type),
"configured for");
1520 snprintf(
status,
sizeof(
status),
"%s %s %s@%s, port %d", cur->unique_name,
type, cur->name, cur->host, cur->port);
1522 snprintf(
status,
sizeof(
status),
"%s %s %s on socket file %s", cur->unique_name,
type, cur->name, cur->sock);
1526 snprintf(status2,
sizeof(status2),
" with username %s", cur->user);
1531 if (ctime > 31536000) {
1532 ast_cli(
a->fd,
"%s%s for %.1f years.\n",
status, status2, (
double)ctime / 31536000.0);
1533 }
else if (ctime > 86400 * 30) {
1534 ast_cli(
a->fd,
"%s%s for %d days.\n",
status, status2, ctime / 86400);
1535 }
else if (ctime > 86400) {
1536 ast_cli(
a->fd,
"%s%s for %d days, %d hours.\n",
status, status2, ctime / 86400, (ctime % 86400) / 3600);
1537 }
else if (ctime > 3600) {
1538 ast_cli(
a->fd,
"%s%s for %d hours, %d minutes.\n",
status, status2, ctime / 3600, (ctime % 3600) / 60);
1539 }
else if (ctime > 60) {
1540 ast_cli(
a->fd,
"%s%s for %d minutes.\n",
status, status2, ctime / 60);
1541 }
else if (ctime > -1) {
1542 ast_cli(
a->fd,
"%s%s for %d seconds.\n",
status, status2, ctime);
1551 ast_cli(
a->fd,
"No connections configured.\n");
1562 .
requires =
"extconfig",
struct sla_ringing_trunk * first
struct sla_ringing_trunk * last
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_calloc(num, len)
A wrapper for calloc()
static time_t connect_time
static const char config[]
General Asterisk PBX channel definitions.
Standard Command Line Interface.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
char * strsep(char **str, const char *delims)
char * strcasestr(const char *, const char *)
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
void ast_category_rename(struct ast_category *cat, const char *name)
#define CONFIG_STATUS_FILEMISSING
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
#define ast_category_new_anonymous()
Create a nameless category that is not backed by a file.
#define ast_variable_new(name, value, filename)
int ast_config_engine_deregister(struct ast_config_engine *del)
Deregister config engine.
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
int ast_rq_is_int(require_type type)
Check if require type is an integer type.
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
require_type
Types used in ast_realtime_require_field.
struct ast_config * ast_config_internal_load(const char *configfile, struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl_file, const char *who_asked)
#define ast_category_new_dynamic(name)
Create a category that is not backed by a file.
int ast_config_engine_register(struct ast_config_engine *newconfig)
Register config engine.
@ CONFIG_FLAG_FILEUNCHANGED
Support for logging to various files, console and syslog Configuration in file logger....
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
#define AST_RWLIST_REMOVE_HEAD
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_LOCK(head)
Locks a list.
#define AST_RWLIST_TRAVERSE
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define AST_RWLIST_INSERT_TAIL
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Asterisk locking-related definitions:
#define ast_mutex_init(pmutex)
#define ast_mutex_unlock(a)
#define ast_mutex_destroy(a)
#define ast_mutex_lock(a)
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODPRI_REALTIME_DRIVER
@ AST_MODULE_SUPPORT_EXTENDED
#define ASTERISK_GPL_KEY
The text the key() function should return.
Options provided by main asterisk program.
static struct ast_threadstorage modify3_buf
static int parse_config(int reload)
static struct ast_config_engine mysql_engine
#define ESCAPE_STRING(buf, var)
static struct ast_threadstorage find_buf
static struct tables * find_table(const char *database, const char *tablename)
static struct ast_cli_entry cli_realtime_mysql_status[]
static void destroy_table(struct tables *table)
static int destroy_mysql(const char *database, const char *table, const char *keyfield, const char *lookup, const struct ast_variable *rt_fields)
static struct ast_threadstorage sql2_buf
static int load_mysql_config(struct ast_config *config, const char *category, struct mysql_conn *conn)
static struct columns * find_column(struct tables *table, const char *colname)
static struct ast_variable * realtime_mysql(const char *database, const char *table, const struct ast_variable *rt_fields)
#define RES_CONFIG_MYSQL_CONF_OLD
#define RES_CONFIG_MYSQL_CONF
static char * ESCAPE_CLAUSE
#define IS_SQL_LIKE_CLAUSE(x)
static char * handle_cli_realtime_mysql_cache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_realtime_mysql_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void release_table(struct tables *table)
static int update2_mysql(const char *database, const char *tablename, const struct ast_variable *lookup_fields, const struct ast_variable *update_fields)
static struct mysql_conn * find_database(const char *database, int for_write)
static int mysql_reconnect(struct mysql_conn *conn)
static struct ast_config * realtime_multi_mysql(const char *database, const char *table, const struct ast_variable *rt_fields)
static struct ast_threadstorage scratch2_buf
static int store_mysql(const char *database, const char *table, const struct ast_variable *rt_fields)
static struct ast_threadstorage modify_buf
static struct ast_config * config_mysql(const char *database, const char *table, const char *file, struct ast_config *cfg, struct ast_flags config_flags, const char *unused, const char *who_asked)
static int load_module(void)
#define release_database(a)
static struct ast_threadstorage scratch_buf
static int unload_module(void)
static int require_mysql(const char *database, const char *tablename, va_list ap)
static int update_mysql(const char *database, const char *tablename, const char *keyfield, const char *lookup, const struct ast_variable *rt_fields)
static int unload_mysql(const char *database, const char *tablename)
static struct ast_threadstorage modify2_buf
static char * decode_chunk(char *chunk)
static struct ast_threadstorage sql_buf
String manipulation functions.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
descriptor for a cli entry.
Configuration engine structure, used to define realtime drivers.
Structure used to handle boolean flags.
Structure for mutex and tracking information.
Support for dynamic strings.
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
struct mysql_conn * database
struct tables::mysql_columns columns
structure to hold users read from users.conf
Definitions to aid in the use of thread local storage.
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
#define ast_clear_flag(p, flag)