[asterisk-addons-commits] tilghman: trunk r362 -
/trunk/res_config_mysql.c
asterisk-addons-commits at lists.digium.com
asterisk-addons-commits at lists.digium.com
Tue Apr 10 16:07:02 MST 2007
Author: tilghman
Date: Tue Apr 10 18:07:02 2007
New Revision: 362
URL: http://svn.digium.com/view/asterisk-addons?view=rev&rev=362
Log:
Issue 5881 - Allow use of separate server connections for read and write operations
Modified:
trunk/res_config_mysql.c
Modified: trunk/res_config_mysql.c
URL: http://svn.digium.com/view/asterisk-addons/trunk/res_config_mysql.c?view=diff&rev=362&r1=361&r2=362
==============================================================================
--- trunk/res_config_mysql.c (original)
+++ trunk/res_config_mysql.c Tue Apr 10 18:07:02 2007
@@ -58,21 +58,27 @@
#define AST_MODULE "res_config_mysql"
-AST_MUTEX_DEFINE_STATIC(mysql_lock);
#define RES_CONFIG_MYSQL_CONF "res_mysql.conf"
-MYSQL mysql;
-static char dbhost[50];
-static char dbuser[50];
-static char dbpass[50];
-static char dbname[50];
-static char dbsock[50];
-static int dbport;
-static int connected;
-static time_t connect_time;
+#define READHANDLE 0
+#define WRITEHANDLE 1
+
+static struct mysql_conn {
+ ast_mutex_t lock;
+ MYSQL handle;
+ char host[50];
+ char name[50];
+ char user[50];
+ char pass[50];
+ char sock[50];
+ int port;
+ int connected;
+ time_t connect_time;
+} dbread, dbwrite;
static int parse_config(void);
-static int mysql_reconnect(const char *database);
+static int mysql_reconnect(struct mysql_conn *conn);
static int realtime_mysql_status(int fd, int argc, char **argv);
+static int load_mysql_config(struct ast_config *config, const char *category, struct mysql_conn *conn);
static char cli_realtime_mysql_status_usage[] =
"Usage: realtime mysql status\n"
@@ -110,9 +116,9 @@
}
/* Must connect to the server before anything else, as the escape function requires the mysql handle. */
- ast_mutex_lock(&mysql_lock);
- if (!mysql_reconnect(database)) {
- ast_mutex_unlock(&mysql_lock);
+ ast_mutex_lock(&dbread.lock);
+ if (!mysql_reconnect(&dbread)) {
+ ast_mutex_unlock(&dbread.lock);
return NULL;
}
@@ -126,7 +132,7 @@
if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&mysql, buf, newval, valsz);
+ mysql_real_escape_string(&dbread.handle, buf, newval, valsz);
snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, buf);
while ((newparam = va_arg(ap, const char *))) {
newval = va_arg(ap, const char *);
@@ -136,7 +142,7 @@
op = "";
if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&mysql, buf, newval, valsz);
+ mysql_real_escape_string(&dbread.handle, buf, newval, valsz);
snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, buf);
}
va_end(ap);
@@ -144,23 +150,21 @@
ast_log(LOG_DEBUG, "MySQL RealTime: Retrieve SQL: %s\n", sql);
/* Execution. */
- if (mysql_real_query(&mysql, sql, strlen(sql))) {
+ if (mysql_real_query(&dbread.handle, sql, strlen(sql))) {
ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
- ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
- ast_mutex_unlock(&mysql_lock);
- return NULL;
- }
-
- if ((result = mysql_store_result(&mysql))) {
+ ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&dbread.handle));
+ ast_mutex_unlock(&dbread.lock);
+ return NULL;
+ }
+
+ if ((result = mysql_store_result(&dbread.handle))) {
numFields = mysql_num_fields(result);
fields = mysql_fetch_fields(result);
while ((row = mysql_fetch_row(result))) {
for (i = 0; i < numFields; i++) {
- stringp = row[i];
- while (stringp) {
- chunk = strsep(&stringp, ";");
+ for (stringp = ast_strdupa(row[i]), chunk = strsep(&stringp, ";"); chunk; chunk = strsep(&stringp, ";")) {
if (chunk && !ast_strlen_zero(ast_strip(chunk))) {
if (prev) {
prev->next = ast_variable_new(fields[i].name, chunk);
@@ -174,11 +178,11 @@
}
}
}
- } else {
+ } else {
ast_log(LOG_WARNING, "MySQL RealTime: Could not find any rows in table %s.\n", table);
}
- ast_mutex_unlock(&mysql_lock);
+ ast_mutex_unlock(&dbread.lock);
mysql_free_result(result);
return var;
@@ -198,7 +202,7 @@
char *op;
const char *newparam, *newval;
struct ast_realloca ra;
- struct ast_variable *var=NULL;
+ struct ast_variable *var = NULL;
struct ast_config *cfg = NULL;
struct ast_category *cat = NULL;
@@ -231,27 +235,31 @@
}
/* Must connect to the server before anything else, as the escape function requires the mysql handle. */
- ast_mutex_lock(&mysql_lock);
- if (!mysql_reconnect(database)) {
- ast_mutex_unlock(&mysql_lock);
+ ast_mutex_lock(&dbread.lock);
+ if (!mysql_reconnect(&dbread)) {
+ ast_mutex_unlock(&dbread.lock);
+ ast_config_destroy(cfg);
return NULL;
}
/* Create the first part of the query using the first parameter/value pairs we just extracted
If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
- if(!strchr(newparam, ' ')) op = " ="; else op = "";
+ if (!strchr(newparam, ' '))
+ op = " =";
+ else
+ op = "";
if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&mysql, buf, newval, valsz);
+ mysql_real_escape_string(&dbread.handle, buf, newval, valsz);
snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, buf);
while ((newparam = va_arg(ap, const char *))) {
newval = va_arg(ap, const char *);
if (!strchr(newparam, ' ')) op = " ="; else op = "";
- if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
+ if ((valsz = strlen(newval)) * 2 + 1 > sizeof(buf))
valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&mysql, buf, newval, valsz);
+ mysql_real_escape_string(&dbread.handle, buf, newval, valsz);
snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, buf);
}
@@ -264,16 +272,16 @@
ast_log(LOG_DEBUG, "MySQL RealTime: Retrieve SQL: %s\n", sql);
/* Execution. */
- if (mysql_real_query(&mysql, sql, strlen(sql))) {
+ if (mysql_real_query(&dbread.handle, sql, strlen(sql))) {
ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
- ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
- ast_mutex_unlock(&mysql_lock);
+ ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&dbread.handle));
+ ast_mutex_unlock(&dbread.lock);
ast_config_destroy(cfg);
return NULL;
}
- if ((result = mysql_store_result(&mysql))) {
+ if ((result = mysql_store_result(&dbread.handle))) {
numFields = mysql_num_fields(result);
fields = mysql_fetch_fields(result);
@@ -285,9 +293,7 @@
continue;
}
for (i = 0; i < numFields; i++) {
- stringp = row[i];
- while (stringp) {
- chunk = strsep(&stringp, ";");
+ for (stringp = ast_strdupa(row[i]), chunk = strsep(&stringp, ";"); chunk; chunk = strsep(&stringp, ";")) {
if (chunk && !ast_strlen_zero(ast_strip(chunk))) {
if (initfield && !strcmp(initfield, fields[i].name)) {
ast_category_rename(cat, chunk);
@@ -303,7 +309,7 @@
ast_log(LOG_WARNING, "MySQL RealTime: Could not find any rows in table %s.\n", table);
}
- ast_mutex_unlock(&mysql_lock);
+ ast_mutex_unlock(&dbread.lock);
mysql_free_result(result);
return cfg;
@@ -319,7 +325,7 @@
if (!table) {
ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
- return -1;
+ return -1;
}
/* Get the first parameter and first value in our list of passed paramater/value pairs */
@@ -331,45 +337,45 @@
}
/* Must connect to the server before anything else, as the escape function requires the mysql handle. */
- ast_mutex_lock(&mysql_lock);
- if (!mysql_reconnect(database)) {
- ast_mutex_unlock(&mysql_lock);
+ ast_mutex_lock(&dbwrite.lock);
+ if (!mysql_reconnect(&dbwrite)) {
+ ast_mutex_unlock(&dbwrite.lock);
return -1;
}
/* Create the first part of the query using the first parameter/value pairs we just extracted
If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
- if ((valsz = strlen (newval)) * 1 + 1 > sizeof(buf))
+ if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&mysql, buf, newval, valsz);
+ mysql_real_escape_string(&dbwrite.handle, buf, newval, valsz);
snprintf(sql, sizeof(sql), "UPDATE %s SET %s = '%s'", table, newparam, buf);
while((newparam = va_arg(ap, const char *))) {
newval = va_arg(ap, const char *);
if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&mysql, buf, newval, valsz);
+ mysql_real_escape_string(&dbwrite.handle, buf, newval, valsz);
snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s = '%s'", newparam, buf);
}
va_end(ap);
- if ((valsz = strlen (lookup)) * 1 + 1 > sizeof(buf))
+ if ((valsz = strlen (lookup)) * 2 + 1 > sizeof(buf))
valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&mysql, buf, lookup, valsz);
+ mysql_real_escape_string(&dbwrite.handle, buf, lookup, valsz);
snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield, buf);
ast_log(LOG_DEBUG,"MySQL RealTime: Update SQL: %s\n", sql);
/* Execution. */
- if (mysql_real_query(&mysql, sql, strlen(sql))) {
+ if (mysql_real_query(&dbwrite.handle, sql, strlen(sql))) {
ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
- ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
- ast_mutex_unlock(&mysql_lock);
- return -1;
- }
-
- numrows = mysql_affected_rows(&mysql);
- ast_mutex_unlock(&mysql_lock);
+ ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&dbwrite.handle));
+ ast_mutex_unlock(&dbwrite.lock);
+ return -1;
+ }
+
+ numrows = mysql_affected_rows(&dbwrite.handle);
+ ast_mutex_unlock(&dbwrite.lock);
ast_log(LOG_DEBUG,"MySQL RealTime: Updated %llu rows on table: %s\n", numrows, table);
@@ -379,10 +385,7 @@
* -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.)
*/
- if (numrows >= 0)
- return (int)numrows;
-
- return -1;
+ return (int)numrows;
}
static int store_mysql(const char *database, const char *table, va_list ap)
@@ -404,65 +407,61 @@
newval = va_arg(ap, const char *);
if (!newparam || !newval) {
ast_log(LOG_WARNING, "MySQL RealTime: Realtime storage requires at least 1 parameter and 1 value to search on.\n");
- mysql_close(&mysql);
return -1;
}
/* Must connect to the server before anything else, as the escape function requires the mysql handle. */
- ast_mutex_lock(&mysql_lock);
- if (!mysql_reconnect(database)) {
- ast_mutex_unlock(&mysql_lock);
+ ast_mutex_lock(&dbwrite.lock);
+ if (!mysql_reconnect(&dbwrite)) {
+ ast_mutex_unlock(&dbwrite.lock);
return -1;
}
/* Create the first part of the query using the first parameter/value pairs we just extracted
If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
- if ((valsz = strlen(newval)) * 1 + 1 > sizeof(buf))
+ if ((valsz = strlen(newval)) * 2 + 1 > sizeof(buf))
valsz = (sizeof(buf) - 1) / 2;
if (newval) {
- mysql_real_escape_string(&mysql, buf, newval, valsz);
+ mysql_real_escape_string(&dbwrite.handle, buf, newval, valsz);
} else {
- buf[0] = 0;
- }
- snprintf(fields, sizeof(fields), "%s",newparam);
- snprintf(values, sizeof(values), "'%s'",buf);
+ buf[0] = '\0';
+ }
+ snprintf(fields, sizeof(fields), "%s", newparam);
+ snprintf(values, sizeof(values), "'%s'", buf);
while ((newparam = va_arg(ap, const char *))) {
newval = va_arg(ap, const char *);
if (newval) {
if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&mysql, buf, newval, valsz);
+ mysql_real_escape_string(&dbwrite.handle, buf, newval, valsz);
} else {
- buf[0] = 0;
+ buf[0] = '\0';
}
- snprintf(fields + strlen(fields), sizeof(fields), ", %s",newparam);
- snprintf(values + strlen(values), sizeof(values), ", '%s'",buf);
+ snprintf(fields + strlen(fields), sizeof(fields), ", %s", newparam);
+ snprintf(values + strlen(values), sizeof(values), ", '%s'", buf);
}
va_end(ap);
snprintf(sql, sizeof(sql), "INSERT into %s (%s) values (%s)", table, fields, values);
ast_log(LOG_DEBUG,"MySQL RealTime: Insert SQL: %s\n", sql);
/* Execution. */
- if (mysql_real_query(&mysql, sql, strlen(sql))) {
+ if (mysql_real_query(&dbwrite.handle, sql, strlen(sql))) {
ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
- ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
- ast_mutex_unlock(&mysql_lock);
- return -1;
- }
-
- insertid = mysql_insert_id(&mysql);
- ast_mutex_unlock(&mysql_lock);
-
- ast_log(LOG_DEBUG,"MySQL RealTime: row inserted on table: %s, id: %llu\n", table, insertid);
+ ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&dbwrite.handle));
+ ast_mutex_unlock(&dbwrite.lock);
+ return -1;
+ }
+
+ insertid = mysql_insert_id(&dbwrite.handle);
+ ast_mutex_unlock(&dbwrite.lock);
+
+ ast_log(LOG_DEBUG, "MySQL RealTime: row inserted on table: %s, id: %llu\n", table, insertid);
/* From http://dev.mysql.com/doc/mysql/en/mysql-affected-rows.html
* An integer greater than zero indicates the number of rows affected
* Zero indicates that no records were updated
* -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.)
*/
- if (insertid >= 0)
- return (int)insertid;
-
- return -1;
+ return (int)insertid;
}
static int destroy_mysql(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
@@ -483,52 +482,47 @@
newval = va_arg(ap, const char *);*/
if (ast_strlen_zero(keyfield) || ast_strlen_zero(lookup)) {
ast_log(LOG_WARNING, "MySQL RealTime: Realtime destroying requires at least 1 parameter and 1 value to search on.\n");
- mysql_close(&mysql);
return -1;
}
/* Must connect to the server before anything else, as the escape function requires the mysql handle. */
- ast_mutex_lock(&mysql_lock);
- if (!mysql_reconnect(database)) {
- ast_mutex_unlock(&mysql_lock);
+ ast_mutex_lock(&dbwrite.lock);
+ if (!mysql_reconnect(&dbwrite)) {
+ ast_mutex_unlock(&dbwrite.lock);
return -1;
}
/* Create the first part of the query using the first parameter/value pairs we just extracted
If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
- if ((valsz = strlen (lookup)) * 1 + 1 > sizeof(buf))
+ if ((valsz = strlen (lookup)) * 2 + 1 > sizeof(buf))
valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&mysql, buf, lookup, valsz);
+ mysql_real_escape_string(&dbwrite.handle, buf, lookup, valsz);
snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE %s = '%s'", table, keyfield, buf);
while ((newparam = va_arg(ap, const char *))) {
newval = va_arg(ap, const char *);
if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
valsz = (sizeof(buf) - 1) / 2;
- mysql_real_escape_string(&mysql, buf, newval, valsz);
+ mysql_real_escape_string(&dbwrite.handle, buf, newval, valsz);
snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s = '%s'", newparam, buf);
}
va_end(ap);
- //if ((valsz = strlen (lookup)) * 1 + 1 > sizeof(buf))
- // valsz = (sizeof(buf) - 1) / 2;
- //mysql_real_escape_string(&mysql, buf, lookup, valsz);
- //snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield, buf);
-
- ast_log(LOG_DEBUG,"MySQL RealTime: Delete SQL: %s\n", sql);
+
+ ast_log(LOG_DEBUG, "MySQL RealTime: Delete SQL: %s\n", sql);
/* Execution. */
- if (mysql_real_query(&mysql, sql, strlen(sql))) {
+ if (mysql_real_query(&dbwrite.handle, sql, strlen(sql))) {
ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
- ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
- ast_mutex_unlock(&mysql_lock);
- return -1;
- }
-
- numrows = mysql_affected_rows(&mysql);
- ast_mutex_unlock(&mysql_lock);
-
- ast_log(LOG_DEBUG,"MySQL RealTime: Deleted %llu rows on table: %s\n", numrows, table);
+ ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&dbwrite.handle));
+ ast_mutex_unlock(&dbwrite.lock);
+ return -1;
+ }
+
+ numrows = mysql_affected_rows(&dbwrite.handle);
+ ast_mutex_unlock(&dbwrite.lock);
+
+ ast_log(LOG_DEBUG, "MySQL RealTime: Deleted %llu rows on table: %s\n", numrows, table);
/* From http://dev.mysql.com/doc/mysql/en/mysql-affected-rows.html
* An integer greater than zero indicates the number of rows affected
@@ -536,10 +530,7 @@
* -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.)
*/
- if (numrows >= 0)
- return (int)numrows;
-
- return -1;
+ return (int)numrows;
}
static struct ast_config *config_mysql(const char *database, const char *table, const char *file, struct ast_config *cfg, int withcomments)
@@ -565,21 +556,21 @@
ast_log(LOG_DEBUG, "MySQL RealTime: Static SQL: %s\n", sql);
/* We now have our complete statement; Lets connect to the server and execute it. */
- ast_mutex_lock(&mysql_lock);
- if (!mysql_reconnect(database)) {
- ast_mutex_unlock(&mysql_lock);
- return NULL;
- }
-
- if (mysql_real_query(&mysql, sql, strlen(sql))) {
+ ast_mutex_lock(&dbread.lock);
+ if (!mysql_reconnect(&dbread)) {
+ ast_mutex_unlock(&dbread.lock);
+ return NULL;
+ }
+
+ if (mysql_real_query(&dbread.handle, sql, strlen(sql))) {
ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
- ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
- ast_mutex_unlock(&mysql_lock);
- return NULL;
- }
-
- if ((result = mysql_store_result(&mysql))) {
+ ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&dbread.handle));
+ ast_mutex_unlock(&dbread.lock);
+ return NULL;
+ }
+
+ if ((result = mysql_store_result(&dbread.handle))) {
num_rows = mysql_num_rows(result);
ast_log(LOG_DEBUG, "MySQL RealTime: Found %llu rows.\n", num_rows);
@@ -590,7 +581,8 @@
if (!strcmp(row[1], "#include")) {
if (!ast_config_internal_load(row[2], cfg, 0)) {
mysql_free_result(result);
- ast_mutex_unlock(&mysql_lock);
+ ast_mutex_unlock(&dbread.lock);
+ ast_config_destroy(cfg);
return NULL;
}
continue;
@@ -615,7 +607,7 @@
}
mysql_free_result(result);
- ast_mutex_unlock(&mysql_lock);
+ ast_mutex_unlock(&dbread.lock);
return cfg;
}
@@ -632,188 +624,216 @@
static int load_module(void)
{
+ int writeokay = 0;
parse_config();
- ast_mutex_lock(&mysql_lock);
-
- if (!mysql_reconnect(NULL)) {
- ast_log(LOG_WARNING, "MySQL RealTime: Couldn't establish connection. Check debug.\n");
- ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
+ ast_mutex_init(&dbread.lock);
+ ast_mutex_init(&dbwrite.lock);
+
+ if (!mysql_reconnect(&dbwrite))
+ ast_log(LOG_WARNING, "MySQL RealTime: Couldn't establish write connection: %s\n", mysql_error(&dbwrite.handle));
+ else
+ writeokay = 1;
+
+ if (!mysql_reconnect(&dbread)) {
+ if (!writeokay)
+ ast_log(LOG_WARNING, "MySQL RealTime: Couldn't establish read connection, either: %s\n", mysql_error(&dbread.handle));
}
ast_config_engine_register(&mysql_engine);
- if (option_verbose) {
- ast_verbose("MySQL RealTime driver loaded.\n");
- }
+ if (option_verbose > 1)
+ ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime driver loaded.\n");
ast_cli_register(&cli_realtime_mysql_status);
- ast_mutex_unlock(&mysql_lock);
-
return 0;
}
static int unload_module(void)
{
- /* Aquire control before doing anything to the module itself. */
- ast_mutex_lock(&mysql_lock);
-
- mysql_close(&mysql);
ast_cli_unregister(&cli_realtime_mysql_status);
ast_config_engine_deregister(&mysql_engine);
- if (option_verbose) {
- ast_verbose("MySQL RealTime unloaded.\n");
- }
+ if (option_verbose > 1)
+ ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime unloaded.\n");
ast_module_user_hangup_all();
- /* Unlock so something else can destroy the lock. */
- ast_mutex_unlock(&mysql_lock);
+ usleep(1);
+ ast_mutex_destroy(&dbread.lock);
+ ast_mutex_destroy(&dbwrite.lock);
+
+ mysql_close(&dbwrite.handle);
+ mysql_close(&dbread.handle);
return 0;
}
static int reload(void)
{
- /* Aquire control before doing anything to the module itself. */
- ast_mutex_lock(&mysql_lock);
-
- mysql_close(&mysql);
- connected = 0;
+ int writeokay = 0;
+
+ ast_mutex_lock(&dbwrite.lock);
+ ast_mutex_lock(&dbread.lock);
+ mysql_close(&dbwrite.handle);
+ mysql_close(&dbread.handle);
parse_config();
- if (!mysql_reconnect(NULL)) {
- ast_log(LOG_WARNING, "MySQL RealTime: Couldn't establish connection. Check debug.\n");
- ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
- }
-
- ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime reloaded.\n");
+ if (!mysql_reconnect(&dbwrite))
+ ast_log(LOG_WARNING, "MySQL RealTime: Cannot connect write handle: %s\n", mysql_error(&dbwrite.handle));
+ else
+ writeokay = 1;
+
+ if (!mysql_reconnect(&dbread)) {
+ if (!writeokay)
+ ast_log(LOG_WARNING, "MySQL RealTime: Cannot Connect read handle, either: %s\n", mysql_error(&dbread.handle));
+ }
+ if (option_verbose > 1)
+ ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime reloaded.\n");
/* Done reloading. Release lock so others can now use driver. */
- ast_mutex_unlock(&mysql_lock);
+ ast_mutex_unlock(&dbread.lock);
+ ast_mutex_unlock(&dbwrite.lock);
return 0;
}
-static int parse_config (void)
+static int parse_config(void)
{
struct ast_config *config;
+
+ config = ast_config_load(RES_CONFIG_MYSQL_CONF);
+
+ if (config) {
+ const char *catg = "write";
+ int haswriteconfig = 0;
+ if (!ast_category_exist(config, catg))
+ catg = "general";
+ if (!ast_category_exist(config, catg))
+ ast_log(LOG_WARNING, "No configuration set for writing to the MySQL database.\n");
+ else
+ haswriteconfig = load_mysql_config(config, catg, &dbwrite);
+
+ if (!ast_category_exist(config, "read")) {
+ if (haswriteconfig) {
+ /* Copy from write config */
+ ast_copy_string(dbread.host, dbwrite.host, sizeof(dbread.host));
+ ast_copy_string(dbread.sock, dbwrite.sock, sizeof(dbread.sock));
+ ast_copy_string(dbread.name, dbwrite.name, sizeof(dbread.name));
+ ast_copy_string(dbread.user, dbwrite.user, sizeof(dbread.user));
+ ast_copy_string(dbread.pass, dbwrite.pass, sizeof(dbread.pass));
+ dbread.port = dbwrite.port;
+ } else
+ ast_log(LOG_WARNING, "It's kind of silly to be loading res_config_mysql.so if there's no configuration settings.\n");
+ } else
+ load_mysql_config(config, "read", &dbread);
+ }
+ ast_config_destroy(config);
+
+ return 0;
+}
+
+static int load_mysql_config(struct ast_config *config, const char *category, struct mysql_conn *conn)
+{
const char *s;
- config = ast_config_load(RES_CONFIG_MYSQL_CONF);
-
- if (config) {
- if (!(s=ast_variable_retrieve(config, "general", "dbuser"))) {
- ast_log(LOG_WARNING, "MySQL RealTime: No database user found, using 'asterisk' as default.\n");
- strncpy(dbuser, "asterisk", sizeof(dbuser) - 1);
- } else {
- strncpy(dbuser, s, sizeof(dbuser) - 1);
- }
-
- if (!(s=ast_variable_retrieve(config, "general", "dbpass"))) {
- ast_log(LOG_WARNING, "MySQL RealTime: No database password found, using 'asterisk' as default.\n");
- strncpy(dbpass, "asterisk", sizeof(dbpass) - 1);
- } else {
- strncpy(dbpass, s, sizeof(dbpass) - 1);
- }
-
- if (!(s=ast_variable_retrieve(config, "general", "dbhost"))) {
- ast_log(LOG_WARNING, "MySQL RealTime: No database host found, using localhost via socket.\n");
- dbhost[0] = '\0';
- } else {
- strncpy(dbhost, s, sizeof(dbhost) - 1);
- }
-
- if (!(s=ast_variable_retrieve(config, "general", "dbname"))) {
- ast_log(LOG_WARNING, "MySQL RealTime: No database name found, using 'asterisk' as default.\n");
- strncpy(dbname, "asterisk", sizeof(dbname) - 1);
- } else {
- strncpy(dbname, s, sizeof(dbname) - 1);
- }
-
- if (!(s=ast_variable_retrieve(config, "general", "dbport"))) {
- ast_log(LOG_WARNING, "MySQL RealTime: No database port found, using 3306 as default.\n");
- dbport = 3306;
- } else {
- dbport = atoi(s);
- }
-
- if (dbhost && !(s=ast_variable_retrieve(config, "general", "dbsock"))) {
- ast_log(LOG_WARNING, "MySQL RealTime: No database socket found, using '/tmp/mysql.sock' as default.\n");
- strncpy(dbsock, "/tmp/mysql.sock", sizeof(dbsock) - 1);
- } else {
- strncpy(dbsock, s, sizeof(dbsock) - 1);
- }
- }
- ast_config_destroy(config);
-
- if (dbhost) {
- ast_log(LOG_DEBUG, "MySQL RealTime Host: %s\n", dbhost);
- ast_log(LOG_DEBUG, "MySQL RealTime Port: %i\n", dbport);
- } else {
- ast_log(LOG_DEBUG, "MySQL RealTime Socket: %s\n", dbsock);
- }
- ast_log(LOG_DEBUG, "MySQL RealTime User: %s\n", dbuser);
- ast_log(LOG_DEBUG, "MySQL RealTime Password: %s\n", dbpass);
+ if (!(s = ast_variable_retrieve(config, category, "dbuser"))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: No database user found, using 'asterisk' as default.\n");
+ s = "asterisk";
+ }
+ ast_copy_string(conn->user, s, sizeof(conn->user));
+
+ if (!(s = ast_variable_retrieve(config, category, "dbpass"))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: No database password found, using 'asterisk' as default.\n");
+ s = "asterisk";
+ }
+ ast_copy_string(conn->pass, s, sizeof(conn->pass));
+
+ if (!(s = ast_variable_retrieve(config, category, "dbhost"))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: No database host found, using localhost via socket.\n");
+ s = "";
+ }
+ ast_copy_string(conn->host, s, sizeof(conn->host));
+
+ if (!(s = ast_variable_retrieve(config, category, "dbname"))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: No database name found, using 'asterisk' as default.\n");
+ s = "asterisk";
+ }
+ ast_copy_string(conn->name, s, sizeof(conn->name) - 1);
+
+ if (!(s = ast_variable_retrieve(config, category, "dbport"))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: No database port found, using 3306 as default.\n");
+ conn->port = 3306;
+ } else
+ conn->port = atoi(s);
+
+ if (!conn->host && !(s = ast_variable_retrieve(config, "general", "dbsock"))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: No database socket found, using '/tmp/mysql.sock' as default.\n");
+ s = "/tmp/mysql.sock";
+ }
+ ast_copy_string(conn->sock, s, sizeof(conn->sock));
+
+
+ if (!ast_strlen_zero(conn->host)) {
+ ast_log(LOG_DEBUG, "MySQL RealTime host: %s\n", conn->host);
+ ast_log(LOG_DEBUG, "MySQL RealTime port: %i\n", conn->port);
+ } else
+ ast_log(LOG_DEBUG, "MySQL RealTime socket: %s\n", conn->sock);
+ ast_log(LOG_DEBUG, "MySQL RealTime database name: %s\n", conn->name);
+ ast_log(LOG_DEBUG, "MySQL RealTime user: %s\n", conn->user);
+ ast_log(LOG_DEBUG, "MySQL RealTime password: %s\n", conn->pass);
return 1;
}
-static int mysql_reconnect(const char *database)
+static int mysql_reconnect(struct mysql_conn *conn)
{
char my_database[50];
#ifdef MYSQL_OPT_RECONNECT
my_bool trueval = 1;
#endif
- if (!database || ast_strlen_zero(database))
- ast_copy_string(my_database, dbname, sizeof(my_database));
- else
- ast_copy_string(my_database, database, sizeof(my_database));
-
/* mutex lock should have been locked before calling this function. */
reconnect_tryagain:
- if ((!connected) && (dbhost || dbsock) && dbuser && dbpass && my_database) {
- if (!mysql_init(&mysql)) {
+ if ((!conn->connected) && (!ast_strlen_zero(conn->host) || conn->sock) && !ast_strlen_zero(conn->user) && !ast_strlen_zero(conn->name)) {
+ if (!mysql_init(&conn->handle)) {
ast_log(LOG_WARNING, "MySQL RealTime: Insufficient memory to allocate MySQL resource.\n");
- connected = 0;
+ conn->connected = 0;
return 0;
}
- if (mysql_real_connect(&mysql, dbhost, dbuser, dbpass, my_database, dbport, dbsock, 0)) {
+ if (mysql_real_connect(&conn->handle, conn->host, conn->user, conn->pass, conn->name, conn->port, conn->sock, 0)) {
#ifdef MYSQL_OPT_RECONNECT
/* The default is no longer to automatically reconnect on failure,
* (as of 5.0.3) so we have to set that option here. */
- mysql_options(&mysql, MYSQL_OPT_RECONNECT, &trueval);
+ mysql_options(&conn->handle, MYSQL_OPT_RECONNECT, &trueval);
#endif
ast_log(LOG_DEBUG, "MySQL RealTime: Successfully connected to database.\n");
- connected = 1;
- connect_time = time(NULL);
+ conn->connected = 1;
+ conn->connect_time = time(NULL);
return 1;
} else {
- ast_log(LOG_ERROR, "MySQL RealTime: Failed to connect database server %s on %s (err %d). Check debug for more info.\n", dbname, dbhost, mysql_errno(&mysql));
- ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect (%d): %s\n", mysql_errno(&mysql), mysql_error(&mysql));
- connected = 0;
+ ast_log(LOG_ERROR, "MySQL RealTime: Failed to connect database server %s on %s (err %d). Check debug for more info.\n", conn->name, !ast_strlen_zero(conn->host) ? conn->host : conn->sock, mysql_errno(&conn->handle));
+ ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect (%d): %s\n", mysql_errno(&conn->handle), mysql_error(&conn->handle));
+ conn->connected = 0;
return 0;
}
} else {
/* MySQL likes to return an error, even if it reconnects successfully.
* So the postman pings twice. */
- if (mysql_ping(&mysql) != 0 && mysql_ping(&mysql) != 0) {
- connected = 0;
- ast_log(LOG_ERROR, "MySQL RealTime: Ping failed (%d). Trying an explicit reconnect.\n", mysql_errno(&mysql));
- ast_log(LOG_DEBUG, "MySQL RealTime: Server Error (%d): %s\n", mysql_errno(&mysql), mysql_error(&mysql));
+ if (mysql_ping(&conn->handle) != 0 && mysql_ping(&conn->handle) != 0) {
+ conn->connected = 0;
+ ast_log(LOG_ERROR, "MySQL RealTime: Ping failed (%d). Trying an explicit reconnect.\n", mysql_errno(&conn->handle));
+ ast_log(LOG_DEBUG, "MySQL RealTime: Server Error (%d): %s\n", mysql_errno(&conn->handle), mysql_error(&conn->handle));
goto reconnect_tryagain;
}
- connected = 1;
-
- if (mysql_select_db(&mysql, my_database) != 0) {
- ast_log(LOG_WARNING, "MySQL RealTime: Unable to select database: %s. Still Connected (%d).\n", my_database, mysql_errno(&mysql));
- ast_log(LOG_DEBUG, "MySQL RealTime: Database Select Failed (%d): %s\n", mysql_error(&mysql), mysql_errno(&mysql));
+ conn->connected = 1;
+
+ if (mysql_select_db(&conn->handle, conn->name) != 0) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Unable to select database: %s. Still Connected (%d) - %s.\n", conn->name, mysql_errno(&conn->handle), mysql_error(&conn->handle));
return 0;
}
- ast_log(LOG_DEBUG, "MySQL RealTime: Everything is fine.\n");
+ ast_log(LOG_DEBUG, "MySQL RealTime: Connection okay.\n");
return 1;
}
}
@@ -821,37 +841,33 @@
static int realtime_mysql_status(int fd, int argc, char **argv)
{
char status[256], status2[100] = "";
- int ctime = time(NULL) - connect_time;
-
- if (mysql_reconnect(NULL)) {
- if (dbhost) {
- snprintf(status, 255, "Connected to %s@%s, port %d", dbname, dbhost, dbport);
- } else if (dbsock) {
- snprintf(status, 255, "Connected to %s on socket file %s", dbname, dbsock);
- } else {
- snprintf(status, 255, "Connected to %s@%s", dbname, dbhost);
- }
-
- if (dbuser && *dbuser) {
- snprintf(status2, 99, " with username %s", dbuser);
- }
-
- if (ctime > 31536000) {
- ast_cli(fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 31536000, (ctime % 31536000) / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
- } else if (ctime > 86400) {
- ast_cli(fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
- } else if (ctime > 3600) {
- ast_cli(fd, "%s%s for %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 3600, (ctime % 3600) / 60, ctime % 60);
- } else if (ctime > 60) {
- ast_cli(fd, "%s%s for %d minutes, %d seconds.\n", status, status2, ctime / 60, ctime % 60);
- } else {
+ int ctime = time(NULL) - dbread.connect_time;
+
+ if (mysql_reconnect(&dbread)) {
+ if (!ast_strlen_zero(dbread.host))
+ snprintf(status, sizeof(status), "Connected to %s@%s, port %d", dbread.name, dbread.host, dbread.port);
+ else
+ snprintf(status, sizeof(status), "Connected to %s on socket file %s", dbread.name, dbread.sock);
+
+ if (!ast_strlen_zero(dbread.user))
+ snprintf(status2, sizeof(status2), " with username %s", dbread.user);
+
+ if (ctime > 31536000)
+ ast_cli(fd, "%s%s for %.1f years.\n", status, status2, (double)ctime / 31536000.0);
+ else if (ctime > 86400 * 30)
+ ast_cli(fd, "%s%s for %d days.\n", status, status2, ctime / 86400);
+ else if (ctime > 86400)
+ ast_cli(fd, "%s%s for %d days, %d hours.\n", status, status2, ctime / 86400, (ctime % 86400) / 3600);
+ else if (ctime > 3600)
+ ast_cli(fd, "%s%s for %d hours, %d minutes.\n", status, status2, ctime / 3600, (ctime % 3600) / 60);
+ else if (ctime > 60)
+ ast_cli(fd, "%s%s for %d minutes.\n", status, status2, ctime / 60);
+ else
ast_cli(fd, "%s%s for %d seconds.\n", status, status2, ctime);
- }
return RESULT_SUCCESS;
- } else {
+ } else
return RESULT_FAILURE;
- }
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "MySQL RealTime Configuration Driver",
More information about the asterisk-addons-commits
mailing list