aboutsummaryrefslogtreecommitdiffstats
path: root/cdr
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2005-02-16 03:52:47 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2005-02-16 03:52:47 +0000
commitcc7e7cd68618c15e56de1d7f8b8d5cc88f409892 (patch)
treee6d7a06fd399d28b70155e0ecf8b4b7ea6f52fd5 /cdr
parent71da10a2665114533201ecb1984d388fd7b62f6f (diff)
Make TDS CDR more resilient (bug #3597)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@5037 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'cdr')
-rwxr-xr-xcdr/cdr_tds.c254
1 files changed, 153 insertions, 101 deletions
diff --git a/cdr/cdr_tds.c b/cdr/cdr_tds.c
index 15a7be84d..c70e62eaf 100755
--- a/cdr/cdr_tds.c
+++ b/cdr/cdr_tds.c
@@ -65,6 +65,10 @@ static char *desc = "MSSQL CDR Backend";
static char *name = "mssql";
static char *config = "cdr_tds.conf";
+static char *hostname = NULL, *dbname = NULL, *dbuser = NULL, *password = NULL, *charset = NULL, *language = NULL;
+
+static int connected = 0;
+
AST_MUTEX_DEFINE_STATIC(tds_lock);
static TDSSOCKET *tds;
@@ -75,11 +79,15 @@ static char *stristr(const char*, const char*);
static char *anti_injection(const char *, int);
static void get_date(char *, struct timeval);
+static int mssql_connect(void);
+static int mssql_disconnect(void);
+
static int tds_log(struct ast_cdr *cdr)
{
char sqlcmd[2048], start[80], answer[80], end[80];
char *accountcode, *src, *dst, *dcontext, *clid, *channel, *dstchannel, *lastapp, *lastdata, *uniqueid;
int res = 0;
+ int retried = 0;
#ifdef TDS_PRE_0_62
TDS_INT result_type;
#endif
@@ -164,16 +172,27 @@ static int tds_log(struct ast_cdr *cdr)
uniqueid
);
+ do {
+ if (!connected) {
+ if (mssql_connect())
+ ast_log(LOG_ERROR, "Failed to reconnect to SQL database.\n");
+ else
+ ast_log(LOG_WARNING, "Reconnected to SQL database.\n");
+
+ retried = 1; /* note that we have now tried */
+ }
+
#ifdef TDS_PRE_0_62
- if ((tds_submit_query(tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds, &result_type) != TDS_SUCCEED || result_type != TDS_CMD_SUCCEED))
+ if (!connected || (tds_submit_query(tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds, &result_type) != TDS_SUCCEED || result_type != TDS_CMD_SUCCEED))
#else
- if ((tds_submit_query(tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds) != TDS_SUCCEED))
+ if (!connected || (tds_submit_query(tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds) != TDS_SUCCEED))
#endif
- {
- ast_log(LOG_ERROR, "Failed to insert record into database.\n");
+ {
+ ast_log(LOG_ERROR, "Failed to insert Call Data Record into SQL database.\n");
- res = -1;
- }
+ mssql_disconnect(); /* this is ok even if we are already disconnected */
+ }
+ } while (!connected && !retried);
free(accountcode);
free(src);
@@ -368,32 +387,129 @@ char *description(void)
return desc;
}
+static int mssql_disconnect(void)
+{
+ if (tds) {
+ tds_free_socket(tds);
+ tds = NULL;
+ }
+
+ if (context) {
+ tds_free_context(context);
+ context = NULL;
+ }
+
+ if (login) {
+ tds_free_login(login);
+ login = NULL;
+ }
+
+ connected = 0;
+
+ return 0;
+}
+
+static int mssql_connect(void)
+{
+ TDSCONNECTINFO *connection = NULL;
+ char query[128];
+
+ /* Connect to M$SQL Server */
+ if (!(login = tds_alloc_login()))
+ {
+ ast_log(LOG_ERROR, "tds_alloc_login() failed.\n");
+ return -1;
+ }
+
+ tds_set_server(login, hostname);
+ tds_set_user(login, dbuser);
+ tds_set_passwd(login, password);
+ tds_set_app(login, "TSQL");
+ tds_set_library(login, "TDS-Library");
+#ifndef TDS_PRE_0_62
+ tds_set_client_charset(login, charset);
+#endif
+ tds_set_language(login, language);
+ tds_set_packet(login, 512);
+ tds_set_version(login, 7, 0);
+
+ if (!(context = tds_alloc_context()))
+ {
+ ast_log(LOG_ERROR, "tds_alloc_context() failed.\n");
+ goto connect_fail;
+ }
+
+ if (!(tds = tds_alloc_socket(context, 512))) {
+ ast_log(LOG_ERROR, "tds_alloc_socket() failed.\n");
+ goto connect_fail;
+ }
+
+ tds_set_parent(tds, NULL);
+ connection = tds_read_config_info(tds, login, context->locale);
+ if (!connection)
+ {
+ ast_log(LOG_ERROR, "tds_read_config() failed.\n");
+ goto connect_fail;
+ }
+
+ if (tds_connect(tds, connection) == TDS_FAIL)
+ {
+ ast_log(LOG_ERROR, "Failed to connect to MSSQL server.\n");
+ tds = NULL; /* freed by tds_connect() on error */
+ tds_free_connect(connection);
+ connection = NULL;
+ goto connect_fail;
+ }
+ tds_free_connect(connection);
+ connection = NULL;
+
+ sprintf(query, "USE %s", dbname);
+#ifdef TDS_PRE_0_62
+ if ((tds_submit_query(tds, query) != TDS_SUCCEED) || (tds_process_simple_query(tds, &result_type) != TDS_SUCCEED || result_type != TDS_CMD_SUCCEED))
+#else
+ if ((tds_submit_query(tds, query) != TDS_SUCCEED) || (tds_process_simple_query(tds) != TDS_SUCCEED))
+#endif
+ {
+ ast_log(LOG_ERROR, "Could not change database (%s)\n", dbname);
+ goto connect_fail;
+ }
+
+ connected = 1;
+ return 0;
+
+connect_fail:
+ mssql_disconnect();
+ return -1;
+}
+
int unload_module(void)
{
- tds_free_socket(tds);
- tds_free_login(login);
- tds_free_context(context);
+ mssql_disconnect();
ast_cdr_unregister(name);
+ if (hostname) free(hostname);
+ if (dbname) free(dbname);
+ if (dbuser) free(dbuser);
+ if (password) free(password);
+ if (charset) free(charset);
+ if (language) free(language);
+
return 0;
}
int load_module(void)
{
- TDSCONNECTINFO *connection;
int res = 0;
struct ast_config *cfg;
struct ast_variable *var;
- char query[1024], *ptr = NULL;
- char *hostname = NULL, *dbname = NULL, *dbuser = NULL, *password = NULL, *charset = NULL, *language = NULL;
+ char *ptr = NULL;
#ifdef TDS_PRE_0_62
TDS_INT result_type;
#endif
cfg = ast_config_load(config);
- if (!cfg)
- {
+ if (!cfg) {
ast_log(LOG_NOTICE, "Unable to load config for MSSQL CDR's: %s\n", config);
return 0;
}
@@ -404,133 +520,69 @@ int load_module(void)
ptr = ast_variable_retrieve(cfg, "global", "hostname");
if (ptr)
- {
- hostname = strdupa(ptr);
- }
+ hostname = strdup(ptr);
else
- {
ast_log(LOG_ERROR,"Database server hostname not specified.\n");
- }
ptr = ast_variable_retrieve(cfg, "global", "dbname");
if (ptr)
- {
- dbname = strdupa(ptr);
- }
+ dbname = strdup(ptr);
else
- {
ast_log(LOG_ERROR,"Database dbname not specified.\n");
- }
ptr = ast_variable_retrieve(cfg, "global", "user");
if (ptr)
- {
- dbuser = strdupa(ptr);
- }
+ dbuser = strdup(ptr);
else
- {
ast_log(LOG_ERROR,"Database dbuser not specified.\n");
- }
ptr = ast_variable_retrieve(cfg, "global", "password");
if (ptr)
- {
- password = strdupa(ptr);
- }
+ password = strdup(ptr);
else
- {
ast_log(LOG_ERROR,"Database password not specified.\n");
- }
ptr = ast_variable_retrieve(cfg, "global", "charset");
if (ptr)
- {
- charset = strdupa(ptr);
- }
+ charset = strdup(ptr);
else
- {
- charset = strdupa("iso_1");
- }
+ charset = strdup("iso_1");
ptr = ast_variable_retrieve(cfg, "global", "language");
if (ptr)
- {
- language = strdupa(ptr);
- }
+ language = strdup(ptr);
else
- {
- language = strdupa("us_english");
- }
+ language = strdup("us_english");
ast_config_destroy(cfg);
- /* Connect to M$SQL Server */
- if (!(login = tds_alloc_login()))
+ mssql_connect();
+
+ /* Register MSSQL CDR handler */
+ res = ast_cdr_register(name, desc, tds_log);
+ if (res)
{
- ast_log(LOG_ERROR, "tds_alloc_login() failed.\n");
- res = -1;
+ ast_log(LOG_ERROR, "Unable to register MSSQL CDR handling\n");
}
- else
- {
- tds_set_server(login, hostname);
- tds_set_user(login, dbuser);
- tds_set_passwd(login, password);
- tds_set_app(login, "TSQL");
- tds_set_library(login, "TDS-Library");
-#ifndef TDS_PRE_0_62
- tds_set_client_charset(login, charset);
-#endif
- tds_set_language(login, language);
- tds_set_packet(login, 512);
- tds_set_version(login, 7, 0);
-
- context = tds_alloc_context();
- tds = tds_alloc_socket(context, 512);
-
- tds_set_parent(tds, NULL);
- connection = tds_read_config_info(NULL, login, context->locale);
- if (!connection || tds_connect(tds, connection) == TDS_FAIL)
- {
- ast_log(LOG_ERROR, "Failed to connect to MSSQL server.\n");
- res = -1;
- }
- tds_free_connect(connection);
- if (!res)
- {
- memset(query, 0, sizeof(query));
- sprintf(query, "USE %s", dbname);
-#ifdef TDS_PRE_0_62
- if ((tds_submit_query(tds, query) != TDS_SUCCEED) || (tds_process_simple_query(tds, &result_type) != TDS_SUCCEED || result_type != TDS_CMD_SUCCEED))
-#else
- if ((tds_submit_query(tds, query) != TDS_SUCCEED) || (tds_process_simple_query(tds) != TDS_SUCCEED))
-#endif
- {
- ast_log(LOG_ERROR, "Could not change database (%s)\n", dbname);
- res = -1;
- }
- else
- {
- /* Register MSSQL CDR handler */
- res = ast_cdr_register(name, desc, tds_log);
- if (res)
- {
- ast_log(LOG_ERROR, "Unable to register MSSQL CDR handling\n");
- }
- }
- }
- }
return res;
}
int reload(void)
{
- return 0;
+ unload_module();
+ return load_module();
}
int usecount(void)
{
- return 0;
+ /* Simplistic use count */
+ if (ast_mutex_trylock(&tds_lock)) {
+ return 1;
+ } else {
+ ast_mutex_unlock(&tds_lock);
+ return 0;
+ }
}
char *key()