handle server going down (bug #3597)

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-0@5063 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Russell Bryant
2005-02-21 04:44:26 +00:00
parent 292059c9cb
commit 1dec1dfb9c

View File

@@ -65,6 +65,11 @@ static char *desc = "MSSQL CDR Backend";
static char *name = "mssql"; static char *name = "mssql";
static char *config = "cdr_tds.conf"; static char *config = "cdr_tds.conf";
static char *hostname = NULL, *dbname = NULL, *dbuser = NULL, *password = NULL, *charset = NULL, *language = NULL;
static int connected = 0;
static time_t connect_time = 0;
AST_MUTEX_DEFINE_STATIC(tds_lock); AST_MUTEX_DEFINE_STATIC(tds_lock);
static TDSSOCKET *tds; static TDSSOCKET *tds;
@@ -75,11 +80,15 @@ static char *stristr(const char*, const char*);
static char *anti_injection(const char *, int); static char *anti_injection(const char *, int);
static void get_date(char *, struct timeval); 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) static int tds_log(struct ast_cdr *cdr)
{ {
char sqlcmd[2048], start[80], answer[80], end[80]; char sqlcmd[2048], start[80], answer[80], end[80];
char *accountcode, *src, *dst, *dcontext, *clid, *channel, *dstchannel, *lastapp, *lastdata, *uniqueid; char *accountcode, *src, *dst, *dcontext, *clid, *channel, *dstchannel, *lastapp, *lastdata, *uniqueid;
int res = 0; int res = 0;
int retried = 0;
#ifdef TDS_PRE_0_62 #ifdef TDS_PRE_0_62
TDS_INT result_type; TDS_INT result_type;
#endif #endif
@@ -164,16 +173,27 @@ static int tds_log(struct ast_cdr *cdr)
uniqueid uniqueid
); );
#ifdef TDS_PRE_0_62 do {
if ((tds_submit_query(tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds, &result_type) != TDS_SUCCEED || result_type != TDS_CMD_SUCCEED)) if (!connected) {
#else if (mssql_connect())
if ((tds_submit_query(tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds) != TDS_SUCCEED)) ast_log(LOG_ERROR, "Failed to reconnect to SQL database.\n");
#endif else
{ ast_log(LOG_WARNING, "Reconnected to SQL database.\n");
ast_log(LOG_ERROR, "Failed to insert record into database.\n");
res = -1; retried = 1; /* note that we have now tried */
} }
#ifdef TDS_PRE_0_62
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 (!connected || (tds_submit_query(tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds) != TDS_SUCCEED))
#endif
{
ast_log(LOG_ERROR, "Failed to insert Call Data Record into SQL database.\n");
mssql_disconnect(); /* this is ok even if we are already disconnected */
}
} while (!connected && !retried);
free(accountcode); free(accountcode);
free(src); free(src);
@@ -368,32 +388,129 @@ char *description(void)
return desc; 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) int unload_module(void)
{ {
tds_free_socket(tds); mssql_disconnect();
tds_free_login(login);
tds_free_context(context);
ast_cdr_unregister(name); 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; return 0;
} }
int load_module(void) int load_module(void)
{ {
TDSCONNECTINFO *connection;
int res = 0; int res = 0;
struct ast_config *cfg; struct ast_config *cfg;
struct ast_variable *var; struct ast_variable *var;
char query[1024], *ptr = NULL; char *ptr = NULL;
char *hostname = NULL, *dbname = NULL, *dbuser = NULL, *password = NULL, *charset = NULL, *language = NULL;
#ifdef TDS_PRE_0_62 #ifdef TDS_PRE_0_62
TDS_INT result_type; TDS_INT result_type;
#endif #endif
cfg = ast_load(config); cfg = ast_load(config);
if (!cfg) if (!cfg) {
{
ast_log(LOG_NOTICE, "Unable to load config for MSSQL CDR's: %s\n", config); ast_log(LOG_NOTICE, "Unable to load config for MSSQL CDR's: %s\n", config);
return 0; return 0;
} }
@@ -404,133 +521,69 @@ int load_module(void)
ptr = ast_variable_retrieve(cfg, "global", "hostname"); ptr = ast_variable_retrieve(cfg, "global", "hostname");
if (ptr) if (ptr)
{ hostname = strdup(ptr);
hostname = strdupa(ptr);
}
else else
{
ast_log(LOG_ERROR,"Database server hostname not specified.\n"); ast_log(LOG_ERROR,"Database server hostname not specified.\n");
}
ptr = ast_variable_retrieve(cfg, "global", "dbname"); ptr = ast_variable_retrieve(cfg, "global", "dbname");
if (ptr) if (ptr)
{ dbname = strdup(ptr);
dbname = strdupa(ptr);
}
else else
{
ast_log(LOG_ERROR,"Database dbname not specified.\n"); ast_log(LOG_ERROR,"Database dbname not specified.\n");
}
ptr = ast_variable_retrieve(cfg, "global", "user"); ptr = ast_variable_retrieve(cfg, "global", "user");
if (ptr) if (ptr)
{ dbuser = strdup(ptr);
dbuser = strdupa(ptr);
}
else else
{
ast_log(LOG_ERROR,"Database dbuser not specified.\n"); ast_log(LOG_ERROR,"Database dbuser not specified.\n");
}
ptr = ast_variable_retrieve(cfg, "global", "password"); ptr = ast_variable_retrieve(cfg, "global", "password");
if (ptr) if (ptr)
{ password = strdup(ptr);
password = strdupa(ptr);
}
else else
{
ast_log(LOG_ERROR,"Database password not specified.\n"); ast_log(LOG_ERROR,"Database password not specified.\n");
}
ptr = ast_variable_retrieve(cfg, "global", "charset"); ptr = ast_variable_retrieve(cfg, "global", "charset");
if (ptr) if (ptr)
{ charset = strdup(ptr);
charset = strdupa(ptr);
}
else else
{ charset = strdup("iso_1");
charset = strdupa("iso_1");
}
ptr = ast_variable_retrieve(cfg, "global", "language"); ptr = ast_variable_retrieve(cfg, "global", "language");
if (ptr) if (ptr)
{ language = strdup(ptr);
language = strdupa(ptr);
}
else else
{ language = strdup("us_english");
language = strdupa("us_english");
}
ast_destroy(cfg); ast_destroy(cfg);
/* Connect to M$SQL Server */ mssql_connect();
if (!(login = tds_alloc_login()))
/* Register MSSQL CDR handler */
res = ast_cdr_register(name, desc, tds_log);
if (res)
{ {
ast_log(LOG_ERROR, "tds_alloc_login() failed.\n"); ast_log(LOG_ERROR, "Unable to register MSSQL CDR handling\n");
res = -1;
} }
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; return res;
} }
int reload(void) int reload(void)
{ {
return 0; unload_module();
return load_module();
} }
int usecount(void) 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() char *key()