summaryrefslogtreecommitdiffstats
path: root/package/asterisk/patches/asterisk-1.2.0-res_mysql.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/asterisk/patches/asterisk-1.2.0-res_mysql.patch')
-rw-r--r--package/asterisk/patches/asterisk-1.2.0-res_mysql.patch698
1 files changed, 698 insertions, 0 deletions
diff --git a/package/asterisk/patches/asterisk-1.2.0-res_mysql.patch b/package/asterisk/patches/asterisk-1.2.0-res_mysql.patch
new file mode 100644
index 000000000..5de810741
--- /dev/null
+++ b/package/asterisk/patches/asterisk-1.2.0-res_mysql.patch
@@ -0,0 +1,698 @@
+diff -ruN asterisk-1.2.0-old/configs/res_mysql.conf.sample asterisk-1.2.0-new/configs/res_mysql.conf.sample
+--- asterisk-1.2.0-old/configs/res_mysql.conf.sample 1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.0-new/configs/res_mysql.conf.sample 2004-12-03 15:33:44.000000000 +0100
+@@ -0,0 +1,15 @@
++;
++; Sample configuration for res_config_mysql.c
++;
++; The value of dbhost may be either a hostname or an IP address.
++; If dbhost is commented out or the string "localhost", a connection
++; to the local host is assumed and dbsock is used instead of TCP/IP
++; to connect to the server.
++;
++[general]
++;dbhost = 127.0.0.1
++;dbname = asterisk
++;dbuser = myuser
++;dbpass = mypass
++;dbport = 3306
++;dbsock = /tmp/mysql.sock
+diff -ruN asterisk-1.2.0-old/res/res_config_mysql.c asterisk-1.2.0-new/res/res_config_mysql.c
+--- asterisk-1.2.0-old/res/res_config_mysql.c 1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.0-new/res/res_config_mysql.c 2005-10-13 21:43:54.000000000 +0200
+@@ -0,0 +1,675 @@
++/*
++ * Asterisk -- A telephony toolkit for Linux.
++ *
++ * Copyright (C) 1999-2005, Digium, Inc.
++ *
++ * Mark Spencer <markster@digium.com> - Asterisk Author
++ * Matthew Boehm <mboehm@cytelcom.com> - MySQL RealTime Driver Author
++ *
++ * res_config_mysql.c <mysql plugin for RealTime configuration engine>
++ *
++ * v2.0 - (10-07-05) - mutex_lock fixes (bug #4973, comment #0034602)
++ *
++ * v1.9 - (08-19-05) - Added support to correctly honor the family database specified
++ * in extconfig.conf (bug #4973)
++ *
++ * v1.8 - (04-21-05) - Modified return values of update_mysql to better indicate
++ * what really happened.
++ *
++ * v1.7 - (01-28-05) - Fixed non-initialization of ast_category struct
++ * in realtime_multi_mysql function which caused segfault.
++ *
++ * v1.6 - (00-00-00) - Skipped to bring comments into sync with version number in CVS.
++ *
++ * v1.5.1 - (01-26-05) - Added better(?) locking stuff
++ *
++ * v1.5 - (01-26-05) - Brought up to date with new config.h changes (bug #3406)
++ * - Added in extra locking provided by georg (bug #3248)
++ *
++ * v1.4 - (12-02-04) - Added realtime_multi_mysql function
++ * This function will return an ast_config with categories,
++ * unlike standard realtime_mysql which only returns
++ * a linked list of ast_variables
++ *
++ * v1.3 - (12-01-04) - Added support other operators
++ * Ex: =, !=, LIKE, NOT LIKE, RLIKE, etc...
++ *
++ * v1.2 - (11-DD-04) - Added reload. Updated load and unload.
++ * Code beautification (doc/CODING-GUIDELINES)
++ */
++
++#include <asterisk/channel.h>
++#include <asterisk/logger.h>
++#include <asterisk/config.h>
++#include <asterisk/module.h>
++#include <asterisk/lock.h>
++#include <asterisk/options.h>
++#include <asterisk/cli.h>
++#include <asterisk/utils.h>
++#include <stdlib.h>
++#include <string.h>
++#include <mysql.h>
++#include <mysql_version.h>
++#include <errmsg.h>
++
++static char *res_config_mysql_desc = "MySQL RealTime Configuration Driver";
++
++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;
++
++static int parse_config(void);
++static int mysql_reconnect(const char *database);
++static int realtime_mysql_status(int fd, int argc, char **argv);
++
++STANDARD_LOCAL_USER;
++
++LOCAL_USER_DECL;
++
++static char cli_realtime_mysql_status_usage[] =
++"Usage: realtime mysql status\n"
++" Shows connection information for the MySQL RealTime driver\n";
++
++static struct ast_cli_entry cli_realtime_mysql_status = {
++ { "realtime", "mysql", "status", NULL }, realtime_mysql_status,
++ "Shows connection information for the MySQL RealTime driver", cli_realtime_mysql_status_usage, NULL };
++
++static struct ast_variable *realtime_mysql(const char *database, const char *table, va_list ap)
++{
++ MYSQL_RES *result;
++ MYSQL_ROW row;
++ MYSQL_FIELD *fields;
++ int numFields, i;
++ char sql[256];
++ char *stringp;
++ char *chunk;
++ char *op;
++ const char *newparam, *newval;
++ struct ast_variable *var=NULL, *prev=NULL;
++
++ if(!table) {
++ ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
++ return NULL;
++ }
++
++ /* Get the first parameter and first value in our list of passed paramater/value pairs */
++ newparam = va_arg(ap, const char *);
++ newval = va_arg(ap, const char *);
++ if(!newparam || !newval) {
++ ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
++ mysql_close(&mysql);
++ 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 = "";
++
++ snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval);
++ while((newparam = va_arg(ap, const char *))) {
++ newval = va_arg(ap, const char *);
++ if(!strchr(newparam, ' ')) op = " ="; else op = "";
++ snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval);
++ }
++ va_end(ap);
++
++ ast_log(LOG_DEBUG, "MySQL RealTime: Retrieve 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_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))) {
++ 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, ";");
++ if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
++ if(prev) {
++ prev->next = ast_variable_new(fields[i].name, chunk);
++ if (prev->next) {
++ prev = prev->next;
++ }
++ } else {
++ prev = var = ast_variable_new(fields[i].name, chunk);
++ }
++ }
++ }
++ }
++ }
++ } else {
++ ast_log(LOG_WARNING, "MySQL RealTime: Could not find any rows in table %s.\n", table);
++ }
++
++ ast_mutex_unlock(&mysql_lock);
++ mysql_free_result(result);
++
++ return var;
++}
++
++static struct ast_config *realtime_multi_mysql(const char *database, const char *table, va_list ap)
++{
++ MYSQL_RES *result;
++ MYSQL_ROW row;
++ MYSQL_FIELD *fields;
++ int numFields, i;
++ char sql[256];
++ const char *initfield = NULL;
++ char *stringp;
++ char *chunk;
++ char *op;
++ const char *newparam, *newval;
++ struct ast_realloca ra;
++ struct ast_variable *var=NULL;
++ struct ast_config *cfg = NULL;
++ struct ast_category *cat = NULL;
++
++ if(!table) {
++ ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
++ return NULL;
++ }
++
++ memset(&ra, 0, sizeof(ra));
++
++ cfg = ast_config_new();
++ if (!cfg) {
++ /* If I can't alloc memory at this point, why bother doing anything else? */
++ ast_log(LOG_WARNING, "Out of memory!\n");
++ return NULL;
++ }
++
++ /* Get the first parameter and first value in our list of passed paramater/value pairs */
++ newparam = va_arg(ap, const char *);
++ newval = va_arg(ap, const char *);
++ if(!newparam || !newval) {
++ ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
++ mysql_close(&mysql);
++ return NULL;
++ }
++
++ initfield = ast_strdupa(newparam);
++ if(initfield && (op = strchr(initfield, ' '))) {
++ *op = '\0';
++ }
++
++ /* 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 = "";
++
++ snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval);
++ while((newparam = va_arg(ap, const char *))) {
++ newval = va_arg(ap, const char *);
++ if(!strchr(newparam, ' ')) op = " ="; else op = "";
++ snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval);
++ }
++
++ if(initfield) {
++ snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
++ }
++
++ va_end(ap);
++
++ ast_log(LOG_DEBUG, "MySQL RealTime: Retrieve 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_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))) {
++ numFields = mysql_num_fields(result);
++ fields = mysql_fetch_fields(result);
++
++ while((row = mysql_fetch_row(result))) {
++ var = NULL;
++ cat = ast_category_new("");
++ if(!cat) {
++ ast_log(LOG_WARNING, "Out of memory!\n");
++ continue;
++ }
++ for(i = 0; i < numFields; i++) {
++ stringp = row[i];
++ while(stringp) {
++ chunk = strsep(&stringp, ";");
++ if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
++ if(initfield && !strcmp(initfield, fields[i].name)) {
++ ast_category_rename(cat, chunk);
++ }
++ var = ast_variable_new(fields[i].name, chunk);
++ ast_variable_append(cat, var);
++ }
++ }
++ }
++ ast_category_append(cfg, cat);
++ }
++ } else {
++ ast_log(LOG_WARNING, "MySQL RealTime: Could not find any rows in table %s.\n", table);
++ }
++
++ ast_mutex_unlock(&mysql_lock);
++ mysql_free_result(result);
++
++ return cfg;
++}
++
++static int update_mysql(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
++{
++ my_ulonglong numrows;
++ char sql[256];
++ const char *newparam, *newval;
++
++ if(!table) {
++ ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
++ return -1;
++ }
++
++ /* Get the first parameter and first value in our list of passed paramater/value pairs */
++ newparam = va_arg(ap, const char *);
++ newval = va_arg(ap, const char *);
++ if(!newparam || !newval) {
++ ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
++ mysql_close(&mysql);
++ 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 */
++
++ snprintf(sql, sizeof(sql), "UPDATE %s SET %s = '%s'", table, newparam, newval);
++ while((newparam = va_arg(ap, const char *))) {
++ newval = va_arg(ap, const char *);
++ snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s = '%s'", newparam, newval);
++ }
++ va_end(ap);
++ snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield, lookup);
++
++ ast_log(LOG_DEBUG,"MySQL RealTime: Update 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 -1;
++ }
++
++ if(mysql_real_query(&mysql, 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: Updated %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
++ * 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(numrows >= 0)
++ return (int)numrows;
++
++ return -1;
++}
++
++static struct ast_config *config_mysql(const char *database, const char *table, const char *file, struct ast_config *cfg)
++{
++ MYSQL_RES *result;
++ MYSQL_ROW row;
++ my_ulonglong num_rows;
++ struct ast_config *new;
++ struct ast_variable *cur_v, *new_v;
++ struct ast_category *cur_cat, *new_cat;
++ char sql[250] = "";
++ char last[80] = "";
++ int cat_started = 0;
++ int var_started = 0;
++ int last_cat_metric = 0;
++
++ last[0] = '\0';
++
++ if(!file || !strcmp(file, RES_CONFIG_MYSQL_CONF)) {
++ ast_log(LOG_WARNING, "MySQL RealTime: Cannot configure myself.\n");
++ return NULL;
++ }
++
++ snprintf(sql, sizeof(sql), "SELECT category, var_name, var_val, cat_metric FROM %s WHERE filename='%s' and commented=0 ORDER BY filename, cat_metric desc, var_metric asc, category, var_name, var_val, id", table, file);
++
++ 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_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))) {
++ num_rows = mysql_num_rows(result);
++ ast_log(LOG_DEBUG, "MySQL RealTime: Found %llu rows.\n", num_rows);
++
++ /* There might exist a better way to access the column names other than counting,
++ but I believe that would require another loop that we don't need. */
++
++ while((row = mysql_fetch_row(result))) {
++ if(!strcmp(row[1], "#include")) {
++ if (!ast_config_internal_load(row[2], cfg)) {
++ mysql_free_result(result);
++ ast_mutex_unlock(&mysql_lock);
++ return NULL;
++ }
++ continue;
++ }
++
++ if(strcmp(last, row[0]) || last_cat_metric != atoi(row[3])) {
++ cur_cat = ast_category_new(row[0]);
++ if (!cur_cat) {
++ ast_log(LOG_WARNING, "Out of memory!\n");
++ break;
++ }
++ strcpy(last, row[0]);
++ last_cat_metric = atoi(row[3]);
++ ast_category_append(cfg, cur_cat);
++ }
++ new_v = ast_variable_new(row[1], row[2]);
++ ast_variable_append(cur_cat, new_v);
++ }
++ } else {
++ ast_log(LOG_WARNING, "MySQL RealTime: Could not find config '%s' in database.\n", file);
++ }
++
++ mysql_free_result(result);
++ ast_mutex_unlock(&mysql_lock);
++
++ return cfg;
++}
++
++static struct ast_config_engine mysql_engine = {
++ .name = "mysql",
++ .load_func = config_mysql,
++ .realtime_func = realtime_mysql,
++ .realtime_multi_func = realtime_multi_mysql,
++ .update_func = update_mysql
++};
++
++int load_module (void)
++{
++ 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_config_engine_register(&mysql_engine);
++ if(option_verbose) {
++ ast_verbose("MySQL RealTime driver loaded.\n");
++ }
++ ast_cli_register(&cli_realtime_mysql_status);
++
++ ast_mutex_unlock(&mysql_lock);
++
++ return 0;
++}
++
++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");
++ }
++
++ STANDARD_HANGUP_LOCALUSERS;
++
++ /* Unlock so something else can destroy the lock. */
++ ast_mutex_unlock(&mysql_lock);
++
++ return 0;
++}
++
++int reload (void)
++{
++ /* Aquire control before doing anything to the module itself. */
++ ast_mutex_lock(&mysql_lock);
++
++ mysql_close(&mysql);
++ connected = 0;
++ 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");
++
++ /* Done reloading. Release lock so others can now use driver. */
++ ast_mutex_unlock(&mysql_lock);
++
++ return 0;
++}
++
++int parse_config (void)
++{
++ struct ast_config *config;
++ 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);
++
++ return 1;
++}
++
++char *description (void)
++{
++ return res_config_mysql_desc;
++}
++
++int usecount (void)
++{
++ /* Try and get a lock. If unsuccessful, than that means another thread is using the mysql object. */
++ if(ast_mutex_trylock(&mysql_lock)) {
++ ast_log(LOG_DEBUG, "MySQL RealTime: Module usage count is 1.\n");
++ return 1;
++ }
++ ast_mutex_unlock(&mysql_lock);
++ return 0;
++}
++
++char *key ()
++{
++ return ASTERISK_GPL_KEY;
++}
++
++static int mysql_reconnect(const char *database)
++{
++ char my_database[50];
++
++ 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. */
++
++ if((!connected) && (dbhost || dbsock) && dbuser && dbpass && my_database) {
++ if(!mysql_init(&mysql)) {
++ ast_log(LOG_WARNING, "MySQL RealTime: Insufficient memory to allocate MySQL resource.\n");
++ connected = 0;
++ return 0;
++ }
++ if(mysql_real_connect(&mysql, dbhost, dbuser, dbpass, my_database, dbport, dbsock, 0)) {
++ ast_log(LOG_DEBUG, "MySQL RealTime: Successfully connected to database.\n");
++ connected = 1;
++ connect_time = time(NULL);
++ return 1;
++ } else {
++ ast_log(LOG_ERROR, "MySQL RealTime: Failed to connect database server %s on %s. Check debug for more info.\n", dbname, dbhost);
++ ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
++ connected = 0;
++ return 0;
++ }
++ } else {
++ if(mysql_ping(&mysql) != 0) {
++ connected = 0;
++ ast_log(LOG_ERROR, "MySQL RealTime: Failed to reconnect. Check debug for more info.\n");
++ ast_log(LOG_DEBUG, "MySQL RealTime: Server Error: %s\n", mysql_error(&mysql));
++ return 0;
++ }
++
++ connected = 1;
++
++ if(mysql_select_db(&mysql, my_database) != 0) {
++ ast_log(LOG_WARNING, "MySQL RealTime: Unable to select database: %s. Still Connected.\n", my_database);
++ ast_log(LOG_DEBUG, "MySQL RealTime: Database Select Failed: %s\n", mysql_error(&mysql));
++ return 0;
++ }
++
++ ast_log(LOG_DEBUG, "MySQL RealTime: Everything is fine.\n");
++ return 1;
++ }
++}
++
++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 {
++ ast_cli(fd, "%s%s for %d seconds.\n", status, status2, ctime);
++ }
++
++ return RESULT_SUCCESS;
++ } else {
++ return RESULT_FAILURE;
++ }
++}