2003-12-02 00:27:28 +00:00
|
|
|
/*
|
2005-09-14 20:46:50 +00:00
|
|
|
* Asterisk -- An open source telephony toolkit.
|
2003-12-02 00:27:28 +00:00
|
|
|
*
|
2005-01-15 09:01:52 +00:00
|
|
|
* Copyright (C) 2003-2005, Digium, Inc.
|
|
|
|
*
|
2003-12-02 00:27:28 +00:00
|
|
|
* Brian K. West <brian@bkw.org>
|
|
|
|
*
|
2005-09-14 20:46:50 +00:00
|
|
|
* See http://www.asterisk.org for more information about
|
|
|
|
* the Asterisk project. Please do not directly contact
|
|
|
|
* any of the maintainers of this project for assistance;
|
|
|
|
* the project provides a web site, mailing lists and IRC
|
|
|
|
* channels for your use.
|
|
|
|
*
|
2003-12-02 00:27:28 +00:00
|
|
|
* This program is free software, distributed under the terms of
|
2005-09-14 20:46:50 +00:00
|
|
|
* the GNU General Public License Version 2. See the LICENSE file
|
|
|
|
* at the top of the source tree.
|
|
|
|
*/
|
|
|
|
|
2005-10-26 13:03:17 +00:00
|
|
|
/*! \file
|
2005-09-14 20:46:50 +00:00
|
|
|
*
|
2005-10-26 13:03:17 +00:00
|
|
|
* \brief ODBC CDR Backend
|
2005-09-14 20:46:50 +00:00
|
|
|
*
|
2005-10-26 13:03:17 +00:00
|
|
|
* \author Brian K. West <brian@bkw.org>
|
|
|
|
*
|
|
|
|
* See also:
|
|
|
|
* \arg http://www.unixodbc.org
|
|
|
|
* \arg \ref Config_cdr
|
2005-11-06 15:09:47 +00:00
|
|
|
* \ingroup cdr_drivers
|
2003-12-02 00:27:28 +00:00
|
|
|
*/
|
|
|
|
|
2006-04-24 17:11:45 +00:00
|
|
|
/*** MODULEINFO
|
|
|
|
<depend>unixodbc</depend>
|
2007-06-18 16:35:02 +00:00
|
|
|
<depend>ltdl</depend>
|
2006-04-24 17:11:45 +00:00
|
|
|
***/
|
|
|
|
|
2006-06-07 18:54:56 +00:00
|
|
|
#include "asterisk.h"
|
|
|
|
|
|
|
|
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|
|
|
|
2003-12-02 00:27:28 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
2005-09-08 02:21:24 +00:00
|
|
|
#ifndef __CYGWIN__
|
2003-12-02 00:27:28 +00:00
|
|
|
#include <sql.h>
|
|
|
|
#include <sqlext.h>
|
|
|
|
#include <sqltypes.h>
|
2005-09-08 02:21:24 +00:00
|
|
|
#else
|
|
|
|
#include <windows.h>
|
|
|
|
#include <w32api/sql.h>
|
|
|
|
#include <w32api/sqlext.h>
|
|
|
|
#include <w32api/sqltypes.h>
|
|
|
|
#endif
|
2003-12-02 00:27:28 +00:00
|
|
|
|
2005-06-06 21:09:59 +00:00
|
|
|
#include "asterisk/config.h"
|
|
|
|
#include "asterisk/options.h"
|
|
|
|
#include "asterisk/channel.h"
|
|
|
|
#include "asterisk/cdr.h"
|
|
|
|
#include "asterisk/module.h"
|
|
|
|
#include "asterisk/logger.h"
|
|
|
|
|
2003-12-02 00:27:28 +00:00
|
|
|
#define DATE_FORMAT "%Y-%m-%d %T"
|
|
|
|
|
2003-12-07 06:43:30 +00:00
|
|
|
static char *name = "ODBC";
|
|
|
|
static char *config = "cdr_odbc.conf";
|
2005-01-15 09:01:52 +00:00
|
|
|
static char *dsn = NULL, *username = NULL, *password = NULL, *table = NULL;
|
|
|
|
static int loguniqueid = 0;
|
2005-02-04 05:52:45 +00:00
|
|
|
static int usegmtime = 0;
|
2005-01-11 18:56:57 +00:00
|
|
|
static int dispositionstring = 0;
|
2005-01-15 09:01:52 +00:00
|
|
|
static int connected = 0;
|
2003-12-02 00:27:28 +00:00
|
|
|
|
2004-06-09 01:45:08 +00:00
|
|
|
AST_MUTEX_DEFINE_STATIC(odbc_lock);
|
2003-12-02 00:27:28 +00:00
|
|
|
|
2003-12-24 00:04:33 +00:00
|
|
|
static int odbc_do_query(void);
|
2003-12-07 17:12:39 +00:00
|
|
|
static int odbc_init(void);
|
2003-12-02 00:27:28 +00:00
|
|
|
|
|
|
|
static SQLHENV ODBC_env = SQL_NULL_HANDLE; /* global ODBC Environment */
|
|
|
|
static SQLHDBC ODBC_con; /* global ODBC Connection Handle */
|
|
|
|
static SQLHSTMT ODBC_stmt; /* global ODBC Statement Handle */
|
|
|
|
|
2006-04-19 18:56:38 +00:00
|
|
|
static void odbc_disconnect(void)
|
|
|
|
{
|
This patch is relevant to:
ABE-1628 and RYM-150398 and AST-103 in internal Digium
bug trackers.
These fixes address a really subtle memory corruption
problem that would happen in machines heavily loaded
in production environments. The corruption would
always take the form of the STMT object getting
nulled out and one of the unixODBC calls would
crash trying to access statement->connection.
It isn't fully proven yet, but the server has
now been running 2.5 days without appreciable
memory growth, or any gain of %cpu, and no
crashes. Whether this is the problem or not
on that server, these fixes are still warranted.
As it turns out, **I** introduced these errors
unwittingly, when I corrected another crash earlier.
I had formed the build_query routine, and failed
to remove mutex_unlock calls in 3 places in the
transplanted code. These unlocks would only
happen in error situations, but unlocking the
mutex early set the code up for a catastrophic
failure, it appears. It would happen only once
every 100K-200K or more calls, under heavy load...
but that is enough.
If another crash occurs, with the same MO,
I'll come back and remove my confession from the log, and
we'll keep searching, but the fact that we
have Asterisk dying from an asynchronous
wiping of the STMT object, only on some connection
error, and that the server has lived for 2.5
days on this code without a crash, sure make
it look like this was the problem!
Also, in several points, Statement handles are
set to NULL after SQLFreeHandle. This was mainly
for insurance, to guarantee a crash. As it turns
out, the code does not appear to be attempting
to use these freed pointers.
Asterisk owes a debt of gratitude to Federico Alves
and Frediano Ziglio for their untiring efforts in
finding this bug, among others.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@150056 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-10-16 15:26:10 +00:00
|
|
|
ODBC_stmt = SQL_NULL_HANDLE;
|
2006-04-19 18:56:38 +00:00
|
|
|
SQLDisconnect(ODBC_con);
|
|
|
|
SQLFreeHandle(SQL_HANDLE_DBC, ODBC_con);
|
This patch is relevant to:
ABE-1628 and RYM-150398 and AST-103 in internal Digium
bug trackers.
These fixes address a really subtle memory corruption
problem that would happen in machines heavily loaded
in production environments. The corruption would
always take the form of the STMT object getting
nulled out and one of the unixODBC calls would
crash trying to access statement->connection.
It isn't fully proven yet, but the server has
now been running 2.5 days without appreciable
memory growth, or any gain of %cpu, and no
crashes. Whether this is the problem or not
on that server, these fixes are still warranted.
As it turns out, **I** introduced these errors
unwittingly, when I corrected another crash earlier.
I had formed the build_query routine, and failed
to remove mutex_unlock calls in 3 places in the
transplanted code. These unlocks would only
happen in error situations, but unlocking the
mutex early set the code up for a catastrophic
failure, it appears. It would happen only once
every 100K-200K or more calls, under heavy load...
but that is enough.
If another crash occurs, with the same MO,
I'll come back and remove my confession from the log, and
we'll keep searching, but the fact that we
have Asterisk dying from an asynchronous
wiping of the STMT object, only on some connection
error, and that the server has lived for 2.5
days on this code without a crash, sure make
it look like this was the problem!
Also, in several points, Statement handles are
set to NULL after SQLFreeHandle. This was mainly
for insurance, to guarantee a crash. As it turns
out, the code does not appear to be attempting
to use these freed pointers.
Asterisk owes a debt of gratitude to Federico Alves
and Frediano Ziglio for their untiring efforts in
finding this bug, among others.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@150056 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-10-16 15:26:10 +00:00
|
|
|
ODBC_con = SQL_NULL_HANDLE;
|
2006-04-19 18:56:38 +00:00
|
|
|
SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
|
This patch is relevant to:
ABE-1628 and RYM-150398 and AST-103 in internal Digium
bug trackers.
These fixes address a really subtle memory corruption
problem that would happen in machines heavily loaded
in production environments. The corruption would
always take the form of the STMT object getting
nulled out and one of the unixODBC calls would
crash trying to access statement->connection.
It isn't fully proven yet, but the server has
now been running 2.5 days without appreciable
memory growth, or any gain of %cpu, and no
crashes. Whether this is the problem or not
on that server, these fixes are still warranted.
As it turns out, **I** introduced these errors
unwittingly, when I corrected another crash earlier.
I had formed the build_query routine, and failed
to remove mutex_unlock calls in 3 places in the
transplanted code. These unlocks would only
happen in error situations, but unlocking the
mutex early set the code up for a catastrophic
failure, it appears. It would happen only once
every 100K-200K or more calls, under heavy load...
but that is enough.
If another crash occurs, with the same MO,
I'll come back and remove my confession from the log, and
we'll keep searching, but the fact that we
have Asterisk dying from an asynchronous
wiping of the STMT object, only on some connection
error, and that the server has lived for 2.5
days on this code without a crash, sure make
it look like this was the problem!
Also, in several points, Statement handles are
set to NULL after SQLFreeHandle. This was mainly
for insurance, to guarantee a crash. As it turns
out, the code does not appear to be attempting
to use these freed pointers.
Asterisk owes a debt of gratitude to Federico Alves
and Frediano Ziglio for their untiring efforts in
finding this bug, among others.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@150056 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-10-16 15:26:10 +00:00
|
|
|
ODBC_env = SQL_NULL_HANDLE;
|
2006-04-19 18:56:38 +00:00
|
|
|
connected = 0;
|
|
|
|
}
|
|
|
|
|
In at least one machine, we noted that the timestr
was not getting set in the STMT; it was coming out,
usually, as binary garbage to an mssql server.
These changes fixed the problem. The only thing
I can venture forth as a guess, is that the pointer
is being stored in the interface, not a copy of the
string. Because we ripped the build process into a
subroutine, the timestr became a temp. stack variable,
and between the time the STMT got built and the
time it was executed on the server, the string being
pointed to was damaged. At any rate, even if this
theory is false, and some mechanism was at fault,
this fix worked reliably where it didn't before.
Why this bug didn't bite last week, I have no idea.
This change basically defines the timestr buffer
in the calling function, extending the life of the
buffer to cover both the STMT's building and
processing to the server.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@143964 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-09-23 14:22:10 +00:00
|
|
|
static void build_query(struct ast_cdr *cdr, char *timestr, int timesize)
|
2003-12-02 00:27:28 +00:00
|
|
|
{
|
2003-12-24 00:04:33 +00:00
|
|
|
int ODBC_res;
|
In at least one machine, we noted that the timestr
was not getting set in the STMT; it was coming out,
usually, as binary garbage to an mssql server.
These changes fixed the problem. The only thing
I can venture forth as a guess, is that the pointer
is being stored in the interface, not a copy of the
string. Because we ripped the build process into a
subroutine, the timestr became a temp. stack variable,
and between the time the STMT got built and the
time it was executed on the server, the string being
pointed to was damaged. At any rate, even if this
theory is false, and some mechanism was at fault,
this fix worked reliably where it didn't before.
Why this bug didn't bite last week, I have no idea.
This change basically defines the timestr buffer
in the calling function, extending the life of the
buffer to cover both the STMT's building and
processing to the server.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@143964 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-09-23 14:22:10 +00:00
|
|
|
char sqlcmd[2048] = "";
|
2003-12-24 00:04:33 +00:00
|
|
|
int res = 0;
|
2003-12-02 00:27:28 +00:00
|
|
|
struct tm tm;
|
|
|
|
|
2005-02-04 05:52:45 +00:00
|
|
|
if (usegmtime)
|
|
|
|
gmtime_r(&cdr->start.tv_sec,&tm);
|
|
|
|
else
|
2007-06-14 21:50:40 +00:00
|
|
|
ast_localtime(&cdr->start.tv_sec, &tm, NULL);
|
2003-12-02 00:27:28 +00:00
|
|
|
|
In at least one machine, we noted that the timestr
was not getting set in the STMT; it was coming out,
usually, as binary garbage to an mssql server.
These changes fixed the problem. The only thing
I can venture forth as a guess, is that the pointer
is being stored in the interface, not a copy of the
string. Because we ripped the build process into a
subroutine, the timestr became a temp. stack variable,
and between the time the STMT got built and the
time it was executed on the server, the string being
pointed to was damaged. At any rate, even if this
theory is false, and some mechanism was at fault,
this fix worked reliably where it didn't before.
Why this bug didn't bite last week, I have no idea.
This change basically defines the timestr buffer
in the calling function, extending the life of the
buffer to cover both the STMT's building and
processing to the server.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@143964 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-09-23 14:22:10 +00:00
|
|
|
strftime(timestr, timesize, DATE_FORMAT, &tm);
|
2003-12-02 00:27:28 +00:00
|
|
|
memset(sqlcmd,0,2048);
|
2005-01-15 09:01:52 +00:00
|
|
|
if (loguniqueid) {
|
2004-12-10 11:59:43 +00:00
|
|
|
snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO %s "
|
2003-12-24 00:04:33 +00:00
|
|
|
"(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,"
|
2004-01-11 06:01:02 +00:00
|
|
|
"lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield) "
|
2004-12-10 11:59:43 +00:00
|
|
|
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", table);
|
2004-10-05 01:05:30 +00:00
|
|
|
} else {
|
2004-12-10 11:59:43 +00:00
|
|
|
snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO %s "
|
2003-12-24 00:04:33 +00:00
|
|
|
"(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,"
|
|
|
|
"duration,billsec,disposition,amaflags,accountcode) "
|
2004-12-10 11:59:43 +00:00
|
|
|
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)", table);
|
2003-12-24 00:04:33 +00:00
|
|
|
}
|
2004-10-05 01:05:30 +00:00
|
|
|
if (!connected) {
|
2005-01-15 09:01:52 +00:00
|
|
|
res = odbc_init();
|
2004-10-05 01:05:30 +00:00
|
|
|
if (res < 0) {
|
2006-04-19 18:56:38 +00:00
|
|
|
odbc_disconnect();
|
2008-09-19 21:07:05 +00:00
|
|
|
return;
|
2003-12-24 00:04:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ODBC_res = SQLAllocHandle(SQL_HANDLE_STMT, ODBC_con, &ODBC_stmt);
|
|
|
|
|
2004-10-05 01:05:30 +00:00
|
|
|
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
|
|
|
|
if (option_verbose > 10)
|
2003-12-24 00:04:33 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Failure in AllocStatement %d\n", ODBC_res);
|
2006-04-19 18:56:38 +00:00
|
|
|
SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
|
This patch is relevant to:
ABE-1628 and RYM-150398 and AST-103 in internal Digium
bug trackers.
These fixes address a really subtle memory corruption
problem that would happen in machines heavily loaded
in production environments. The corruption would
always take the form of the STMT object getting
nulled out and one of the unixODBC calls would
crash trying to access statement->connection.
It isn't fully proven yet, but the server has
now been running 2.5 days without appreciable
memory growth, or any gain of %cpu, and no
crashes. Whether this is the problem or not
on that server, these fixes are still warranted.
As it turns out, **I** introduced these errors
unwittingly, when I corrected another crash earlier.
I had formed the build_query routine, and failed
to remove mutex_unlock calls in 3 places in the
transplanted code. These unlocks would only
happen in error situations, but unlocking the
mutex early set the code up for a catastrophic
failure, it appears. It would happen only once
every 100K-200K or more calls, under heavy load...
but that is enough.
If another crash occurs, with the same MO,
I'll come back and remove my confession from the log, and
we'll keep searching, but the fact that we
have Asterisk dying from an asynchronous
wiping of the STMT object, only on some connection
error, and that the server has lived for 2.5
days on this code without a crash, sure make
it look like this was the problem!
Also, in several points, Statement handles are
set to NULL after SQLFreeHandle. This was mainly
for insurance, to guarantee a crash. As it turns
out, the code does not appear to be attempting
to use these freed pointers.
Asterisk owes a debt of gratitude to Federico Alves
and Frediano Ziglio for their untiring efforts in
finding this bug, among others.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@150056 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-10-16 15:26:10 +00:00
|
|
|
ODBC_stmt = SQL_NULL_HANDLE;
|
2006-04-19 18:56:38 +00:00
|
|
|
odbc_disconnect();
|
2008-09-19 21:07:05 +00:00
|
|
|
return;
|
2003-12-07 17:12:39 +00:00
|
|
|
}
|
|
|
|
|
2003-12-24 00:04:33 +00:00
|
|
|
/* We really should only have to do this once. But for some
|
|
|
|
strange reason if I don't it blows holes in memory like
|
|
|
|
like a shotgun. So we just do this so its safe. */
|
|
|
|
|
2006-03-01 17:53:05 +00:00
|
|
|
ODBC_res = SQLPrepare(ODBC_stmt, (unsigned char *)sqlcmd, SQL_NTS);
|
2003-12-24 00:04:33 +00:00
|
|
|
|
2004-10-05 01:05:30 +00:00
|
|
|
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
|
|
|
|
if (option_verbose > 10)
|
2003-12-24 00:04:33 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error in PREPARE %d\n", ODBC_res);
|
|
|
|
SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
|
This patch is relevant to:
ABE-1628 and RYM-150398 and AST-103 in internal Digium
bug trackers.
These fixes address a really subtle memory corruption
problem that would happen in machines heavily loaded
in production environments. The corruption would
always take the form of the STMT object getting
nulled out and one of the unixODBC calls would
crash trying to access statement->connection.
It isn't fully proven yet, but the server has
now been running 2.5 days without appreciable
memory growth, or any gain of %cpu, and no
crashes. Whether this is the problem or not
on that server, these fixes are still warranted.
As it turns out, **I** introduced these errors
unwittingly, when I corrected another crash earlier.
I had formed the build_query routine, and failed
to remove mutex_unlock calls in 3 places in the
transplanted code. These unlocks would only
happen in error situations, but unlocking the
mutex early set the code up for a catastrophic
failure, it appears. It would happen only once
every 100K-200K or more calls, under heavy load...
but that is enough.
If another crash occurs, with the same MO,
I'll come back and remove my confession from the log, and
we'll keep searching, but the fact that we
have Asterisk dying from an asynchronous
wiping of the STMT object, only on some connection
error, and that the server has lived for 2.5
days on this code without a crash, sure make
it look like this was the problem!
Also, in several points, Statement handles are
set to NULL after SQLFreeHandle. This was mainly
for insurance, to guarantee a crash. As it turns
out, the code does not appear to be attempting
to use these freed pointers.
Asterisk owes a debt of gratitude to Federico Alves
and Frediano Ziglio for their untiring efforts in
finding this bug, among others.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@150056 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-10-16 15:26:10 +00:00
|
|
|
ODBC_stmt = SQL_NULL_HANDLE;
|
2006-04-19 18:56:38 +00:00
|
|
|
odbc_disconnect();
|
2008-09-19 21:07:05 +00:00
|
|
|
return;
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
2003-12-24 00:04:33 +00:00
|
|
|
|
In at least one machine, we noted that the timestr
was not getting set in the STMT; it was coming out,
usually, as binary garbage to an mssql server.
These changes fixed the problem. The only thing
I can venture forth as a guess, is that the pointer
is being stored in the interface, not a copy of the
string. Because we ripped the build process into a
subroutine, the timestr became a temp. stack variable,
and between the time the STMT got built and the
time it was executed on the server, the string being
pointed to was damaged. At any rate, even if this
theory is false, and some mechanism was at fault,
this fix worked reliably where it didn't before.
Why this bug didn't bite last week, I have no idea.
This change basically defines the timestr buffer
in the calling function, extending the life of the
buffer to cover both the STMT's building and
processing to the server.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@143964 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-09-23 14:22:10 +00:00
|
|
|
SQLBindParameter(ODBC_stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, timesize, 0, timestr, 0, NULL);
|
2004-05-21 00:40:02 +00:00
|
|
|
SQLBindParameter(ODBC_stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->clid), 0, cdr->clid, 0, NULL);
|
|
|
|
SQLBindParameter(ODBC_stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->src), 0, cdr->src, 0, NULL);
|
|
|
|
SQLBindParameter(ODBC_stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dst), 0, cdr->dst, 0, NULL);
|
|
|
|
SQLBindParameter(ODBC_stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dcontext), 0, cdr->dcontext, 0, NULL);
|
|
|
|
SQLBindParameter(ODBC_stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->channel), 0, cdr->channel, 0, NULL);
|
|
|
|
SQLBindParameter(ODBC_stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dstchannel), 0, cdr->dstchannel, 0, NULL);
|
|
|
|
SQLBindParameter(ODBC_stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastapp), 0, cdr->lastapp, 0, NULL);
|
|
|
|
SQLBindParameter(ODBC_stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastdata), 0, cdr->lastdata, 0, NULL);
|
2004-01-22 21:27:07 +00:00
|
|
|
SQLBindParameter(ODBC_stmt, 10, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->duration, 0, NULL);
|
|
|
|
SQLBindParameter(ODBC_stmt, 11, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->billsec, 0, NULL);
|
2005-01-11 18:56:57 +00:00
|
|
|
if (dispositionstring)
|
2005-01-11 21:25:21 +00:00
|
|
|
SQLBindParameter(ODBC_stmt, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(ast_cdr_disp2str(cdr->disposition)) + 1, 0, ast_cdr_disp2str(cdr->disposition), 0, NULL);
|
2005-01-11 18:56:57 +00:00
|
|
|
else
|
|
|
|
SQLBindParameter(ODBC_stmt, 12, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->disposition, 0, NULL);
|
2004-01-22 21:27:07 +00:00
|
|
|
SQLBindParameter(ODBC_stmt, 13, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->amaflags, 0, NULL);
|
2004-05-21 00:40:02 +00:00
|
|
|
SQLBindParameter(ODBC_stmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->accountcode), 0, cdr->accountcode, 0, NULL);
|
2003-12-24 00:04:33 +00:00
|
|
|
|
2005-01-15 09:01:52 +00:00
|
|
|
if (loguniqueid) {
|
2004-05-21 00:40:02 +00:00
|
|
|
SQLBindParameter(ODBC_stmt, 15, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->uniqueid), 0, cdr->uniqueid, 0, NULL);
|
|
|
|
SQLBindParameter(ODBC_stmt, 16, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->userfield), 0, cdr->userfield, 0, NULL);
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
2008-09-19 21:07:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int odbc_log(struct ast_cdr *cdr)
|
|
|
|
{
|
|
|
|
int res = 0;
|
In at least one machine, we noted that the timestr
was not getting set in the STMT; it was coming out,
usually, as binary garbage to an mssql server.
These changes fixed the problem. The only thing
I can venture forth as a guess, is that the pointer
is being stored in the interface, not a copy of the
string. Because we ripped the build process into a
subroutine, the timestr became a temp. stack variable,
and between the time the STMT got built and the
time it was executed on the server, the string being
pointed to was damaged. At any rate, even if this
theory is false, and some mechanism was at fault,
this fix worked reliably where it didn't before.
Why this bug didn't bite last week, I have no idea.
This change basically defines the timestr buffer
in the calling function, extending the life of the
buffer to cover both the STMT's building and
processing to the server.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@143964 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-09-23 14:22:10 +00:00
|
|
|
char timestr[150];
|
2008-09-19 21:07:05 +00:00
|
|
|
|
|
|
|
ast_mutex_lock(&odbc_lock);
|
In at least one machine, we noted that the timestr
was not getting set in the STMT; it was coming out,
usually, as binary garbage to an mssql server.
These changes fixed the problem. The only thing
I can venture forth as a guess, is that the pointer
is being stored in the interface, not a copy of the
string. Because we ripped the build process into a
subroutine, the timestr became a temp. stack variable,
and between the time the STMT got built and the
time it was executed on the server, the string being
pointed to was damaged. At any rate, even if this
theory is false, and some mechanism was at fault,
this fix worked reliably where it didn't before.
Why this bug didn't bite last week, I have no idea.
This change basically defines the timestr buffer
in the calling function, extending the life of the
buffer to cover both the STMT's building and
processing to the server.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@143964 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-09-23 14:22:10 +00:00
|
|
|
build_query(cdr, timestr, sizeof(timestr));
|
2003-12-02 00:27:28 +00:00
|
|
|
|
2004-10-05 01:05:30 +00:00
|
|
|
if (connected) {
|
2003-12-24 00:04:33 +00:00
|
|
|
res = odbc_do_query();
|
2004-10-05 01:05:30 +00:00
|
|
|
if (res < 0) {
|
|
|
|
if (option_verbose > 10)
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Reconnecting to dsn %s\n", dsn);
|
2008-09-19 21:07:05 +00:00
|
|
|
odbc_disconnect();
|
2006-04-19 18:56:38 +00:00
|
|
|
res = odbc_init();
|
2004-10-05 01:05:30 +00:00
|
|
|
if (res < 0) {
|
|
|
|
if (option_verbose > 10)
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: %s has gone away!\n", dsn);
|
2006-04-19 18:56:38 +00:00
|
|
|
odbc_disconnect();
|
2004-10-05 01:05:30 +00:00
|
|
|
} else {
|
|
|
|
if (option_verbose > 10)
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Trying Query again!\n");
|
2008-09-19 21:07:05 +00:00
|
|
|
SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
|
This patch is relevant to:
ABE-1628 and RYM-150398 and AST-103 in internal Digium
bug trackers.
These fixes address a really subtle memory corruption
problem that would happen in machines heavily loaded
in production environments. The corruption would
always take the form of the STMT object getting
nulled out and one of the unixODBC calls would
crash trying to access statement->connection.
It isn't fully proven yet, but the server has
now been running 2.5 days without appreciable
memory growth, or any gain of %cpu, and no
crashes. Whether this is the problem or not
on that server, these fixes are still warranted.
As it turns out, **I** introduced these errors
unwittingly, when I corrected another crash earlier.
I had formed the build_query routine, and failed
to remove mutex_unlock calls in 3 places in the
transplanted code. These unlocks would only
happen in error situations, but unlocking the
mutex early set the code up for a catastrophic
failure, it appears. It would happen only once
every 100K-200K or more calls, under heavy load...
but that is enough.
If another crash occurs, with the same MO,
I'll come back and remove my confession from the log, and
we'll keep searching, but the fact that we
have Asterisk dying from an asynchronous
wiping of the STMT object, only on some connection
error, and that the server has lived for 2.5
days on this code without a crash, sure make
it look like this was the problem!
Also, in several points, Statement handles are
set to NULL after SQLFreeHandle. This was mainly
for insurance, to guarantee a crash. As it turns
out, the code does not appear to be attempting
to use these freed pointers.
Asterisk owes a debt of gratitude to Federico Alves
and Frediano Ziglio for their untiring efforts in
finding this bug, among others.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@150056 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-10-16 15:26:10 +00:00
|
|
|
ODBC_stmt = SQL_NULL_HANDLE;
|
In at least one machine, we noted that the timestr
was not getting set in the STMT; it was coming out,
usually, as binary garbage to an mssql server.
These changes fixed the problem. The only thing
I can venture forth as a guess, is that the pointer
is being stored in the interface, not a copy of the
string. Because we ripped the build process into a
subroutine, the timestr became a temp. stack variable,
and between the time the STMT got built and the
time it was executed on the server, the string being
pointed to was damaged. At any rate, even if this
theory is false, and some mechanism was at fault,
this fix worked reliably where it didn't before.
Why this bug didn't bite last week, I have no idea.
This change basically defines the timestr buffer
in the calling function, extending the life of the
buffer to cover both the STMT's building and
processing to the server.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@143964 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-09-23 14:22:10 +00:00
|
|
|
build_query(cdr, timestr, sizeof(timestr)); /* what a waste. If we have to reconnect, we have to build a new query */
|
2003-12-24 00:04:33 +00:00
|
|
|
res = odbc_do_query();
|
2004-10-05 01:05:30 +00:00
|
|
|
if (res < 0) {
|
|
|
|
if (option_verbose > 10)
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query FAILED Call not logged!\n");
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-10-05 01:05:30 +00:00
|
|
|
} else {
|
|
|
|
if (option_verbose > 10)
|
2003-12-24 00:04:33 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query FAILED Call not logged!\n");
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
2004-11-25 06:13:29 +00:00
|
|
|
SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
|
This patch is relevant to:
ABE-1628 and RYM-150398 and AST-103 in internal Digium
bug trackers.
These fixes address a really subtle memory corruption
problem that would happen in machines heavily loaded
in production environments. The corruption would
always take the form of the STMT object getting
nulled out and one of the unixODBC calls would
crash trying to access statement->connection.
It isn't fully proven yet, but the server has
now been running 2.5 days without appreciable
memory growth, or any gain of %cpu, and no
crashes. Whether this is the problem or not
on that server, these fixes are still warranted.
As it turns out, **I** introduced these errors
unwittingly, when I corrected another crash earlier.
I had formed the build_query routine, and failed
to remove mutex_unlock calls in 3 places in the
transplanted code. These unlocks would only
happen in error situations, but unlocking the
mutex early set the code up for a catastrophic
failure, it appears. It would happen only once
every 100K-200K or more calls, under heavy load...
but that is enough.
If another crash occurs, with the same MO,
I'll come back and remove my confession from the log, and
we'll keep searching, but the fact that we
have Asterisk dying from an asynchronous
wiping of the STMT object, only on some connection
error, and that the server has lived for 2.5
days on this code without a crash, sure make
it look like this was the problem!
Also, in several points, Statement handles are
set to NULL after SQLFreeHandle. This was mainly
for insurance, to guarantee a crash. As it turns
out, the code does not appear to be attempting
to use these freed pointers.
Asterisk owes a debt of gratitude to Federico Alves
and Frediano Ziglio for their untiring efforts in
finding this bug, among others.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@150056 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-10-16 15:26:10 +00:00
|
|
|
ODBC_stmt = SQL_NULL_HANDLE;
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_mutex_unlock(&odbc_lock);
|
2003-12-02 00:27:28 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-12-07 06:43:30 +00:00
|
|
|
static int odbc_unload_module(void)
|
2003-12-02 00:27:28 +00:00
|
|
|
{
|
2003-12-24 00:04:33 +00:00
|
|
|
ast_mutex_lock(&odbc_lock);
|
2004-10-05 01:05:30 +00:00
|
|
|
if (connected) {
|
|
|
|
if (option_verbose > 10)
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Disconnecting from %s\n", dsn);
|
2003-12-02 00:27:28 +00:00
|
|
|
SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
|
This patch is relevant to:
ABE-1628 and RYM-150398 and AST-103 in internal Digium
bug trackers.
These fixes address a really subtle memory corruption
problem that would happen in machines heavily loaded
in production environments. The corruption would
always take the form of the STMT object getting
nulled out and one of the unixODBC calls would
crash trying to access statement->connection.
It isn't fully proven yet, but the server has
now been running 2.5 days without appreciable
memory growth, or any gain of %cpu, and no
crashes. Whether this is the problem or not
on that server, these fixes are still warranted.
As it turns out, **I** introduced these errors
unwittingly, when I corrected another crash earlier.
I had formed the build_query routine, and failed
to remove mutex_unlock calls in 3 places in the
transplanted code. These unlocks would only
happen in error situations, but unlocking the
mutex early set the code up for a catastrophic
failure, it appears. It would happen only once
every 100K-200K or more calls, under heavy load...
but that is enough.
If another crash occurs, with the same MO,
I'll come back and remove my confession from the log, and
we'll keep searching, but the fact that we
have Asterisk dying from an asynchronous
wiping of the STMT object, only on some connection
error, and that the server has lived for 2.5
days on this code without a crash, sure make
it look like this was the problem!
Also, in several points, Statement handles are
set to NULL after SQLFreeHandle. This was mainly
for insurance, to guarantee a crash. As it turns
out, the code does not appear to be attempting
to use these freed pointers.
Asterisk owes a debt of gratitude to Federico Alves
and Frediano Ziglio for their untiring efforts in
finding this bug, among others.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@150056 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-10-16 15:26:10 +00:00
|
|
|
ODBC_stmt = SQL_NULL_HANDLE;
|
2006-04-19 18:56:38 +00:00
|
|
|
odbc_disconnect();
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
2005-07-11 21:06:27 +00:00
|
|
|
if (dsn) {
|
2004-10-05 01:05:30 +00:00
|
|
|
if (option_verbose > 10)
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free dsn\n");
|
2003-12-02 00:27:28 +00:00
|
|
|
free(dsn);
|
|
|
|
}
|
2005-07-11 21:06:27 +00:00
|
|
|
if (username) {
|
2004-10-05 01:05:30 +00:00
|
|
|
if (option_verbose > 10)
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free username\n");
|
2003-12-02 00:27:28 +00:00
|
|
|
free(username);
|
|
|
|
}
|
2005-07-11 21:06:27 +00:00
|
|
|
if (password) {
|
2004-10-05 01:05:30 +00:00
|
|
|
if (option_verbose > 10)
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free password\n");
|
2003-12-02 00:27:28 +00:00
|
|
|
free(password);
|
|
|
|
}
|
2005-07-11 21:06:27 +00:00
|
|
|
if (table) {
|
2004-12-10 11:59:43 +00:00
|
|
|
if (option_verbose > 10)
|
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free table\n");
|
|
|
|
free(table);
|
|
|
|
}
|
2005-01-15 09:01:52 +00:00
|
|
|
|
2003-12-02 00:27:28 +00:00
|
|
|
ast_cdr_unregister(name);
|
2003-12-24 00:04:33 +00:00
|
|
|
ast_mutex_unlock(&odbc_lock);
|
2003-12-02 00:27:28 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-12-07 06:43:30 +00:00
|
|
|
static int odbc_load_module(void)
|
2003-12-02 00:27:28 +00:00
|
|
|
{
|
2004-01-04 05:11:53 +00:00
|
|
|
int res = 0;
|
2003-12-02 00:27:28 +00:00
|
|
|
struct ast_config *cfg;
|
|
|
|
struct ast_variable *var;
|
2006-09-20 20:40:39 +00:00
|
|
|
const char *tmp;
|
2003-12-02 00:27:28 +00:00
|
|
|
|
2003-12-24 00:04:33 +00:00
|
|
|
ast_mutex_lock(&odbc_lock);
|
|
|
|
|
2005-01-25 06:10:20 +00:00
|
|
|
cfg = ast_config_load(config);
|
2004-10-05 01:05:30 +00:00
|
|
|
if (!cfg) {
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_log(LOG_WARNING, "cdr_odbc: Unable to load config for ODBC CDR's: %s\n", config);
|
2006-08-31 21:00:20 +00:00
|
|
|
res = AST_MODULE_LOAD_DECLINE;
|
2004-01-04 05:11:53 +00:00
|
|
|
goto out;
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var = ast_variable_browse(cfg, "global");
|
|
|
|
if (!var) {
|
|
|
|
/* nothing configured */
|
2004-01-04 05:11:53 +00:00
|
|
|
goto out;
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tmp = ast_variable_retrieve(cfg,"global","dsn");
|
2005-07-11 21:06:27 +00:00
|
|
|
if (tmp == NULL) {
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_log(LOG_WARNING,"cdr_odbc: dsn not specified. Assuming asteriskdb\n");
|
2005-07-11 21:06:27 +00:00
|
|
|
tmp = "asteriskdb";
|
|
|
|
}
|
|
|
|
dsn = strdup(tmp);
|
|
|
|
if (dsn == NULL) {
|
|
|
|
ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
|
|
|
|
res = -1;
|
|
|
|
goto out;
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
|
|
|
|
2005-01-11 18:56:57 +00:00
|
|
|
tmp = ast_variable_retrieve(cfg,"global","dispositionstring");
|
2005-01-15 09:01:52 +00:00
|
|
|
if (tmp) {
|
2005-01-11 18:56:57 +00:00
|
|
|
dispositionstring = ast_true(tmp);
|
2005-01-15 09:01:52 +00:00
|
|
|
} else {
|
|
|
|
dispositionstring = 0;
|
|
|
|
}
|
2005-01-11 18:56:57 +00:00
|
|
|
|
2003-12-02 00:27:28 +00:00
|
|
|
tmp = ast_variable_retrieve(cfg,"global","username");
|
2004-10-05 01:05:30 +00:00
|
|
|
if (tmp) {
|
2005-07-11 21:06:27 +00:00
|
|
|
username = strdup(tmp);
|
|
|
|
if (username == NULL) {
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
|
2005-01-15 09:01:52 +00:00
|
|
|
res = -1;
|
|
|
|
goto out;
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = ast_variable_retrieve(cfg,"global","password");
|
2004-10-05 01:05:30 +00:00
|
|
|
if (tmp) {
|
2005-07-11 21:06:27 +00:00
|
|
|
password = strdup(tmp);
|
|
|
|
if (password == NULL) {
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
|
2005-01-15 09:01:52 +00:00
|
|
|
res = -1;
|
|
|
|
goto out;
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = ast_variable_retrieve(cfg,"global","loguniqueid");
|
2004-10-05 01:05:30 +00:00
|
|
|
if (tmp) {
|
2005-01-15 09:01:52 +00:00
|
|
|
loguniqueid = ast_true(tmp);
|
|
|
|
if (loguniqueid) {
|
2005-02-04 05:52:45 +00:00
|
|
|
ast_log(LOG_DEBUG,"cdr_odbc: Logging uniqueid\n");
|
2004-10-05 01:05:30 +00:00
|
|
|
} else {
|
2005-02-04 05:52:45 +00:00
|
|
|
ast_log(LOG_DEBUG,"cdr_odbc: Not logging uniqueid\n");
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
2004-10-05 01:05:30 +00:00
|
|
|
} else {
|
2005-02-04 05:52:45 +00:00
|
|
|
ast_log(LOG_DEBUG,"cdr_odbc: Not logging uniqueid\n");
|
2005-01-15 09:01:52 +00:00
|
|
|
loguniqueid = 0;
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
|
|
|
|
2005-02-04 05:52:45 +00:00
|
|
|
tmp = ast_variable_retrieve(cfg,"global","usegmtime");
|
|
|
|
if (tmp) {
|
|
|
|
usegmtime = ast_true(tmp);
|
|
|
|
if (usegmtime) {
|
|
|
|
ast_log(LOG_DEBUG,"cdr_odbc: Logging in GMT\n");
|
|
|
|
} else {
|
|
|
|
ast_log(LOG_DEBUG,"cdr_odbc: Not logging in GMT\n");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ast_log(LOG_DEBUG,"cdr_odbc: Not logging in GMT\n");
|
|
|
|
usegmtime = 0;
|
|
|
|
}
|
|
|
|
|
2004-12-10 11:59:43 +00:00
|
|
|
tmp = ast_variable_retrieve(cfg,"global","table");
|
2005-07-11 21:06:27 +00:00
|
|
|
if (tmp == NULL) {
|
2004-12-10 11:59:43 +00:00
|
|
|
ast_log(LOG_WARNING,"cdr_odbc: table not specified. Assuming cdr\n");
|
2005-07-11 21:06:27 +00:00
|
|
|
tmp = "cdr";
|
|
|
|
}
|
|
|
|
table = strdup(tmp);
|
|
|
|
if (table == NULL) {
|
|
|
|
ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
|
|
|
|
res = -1;
|
|
|
|
goto out;
|
2004-12-10 11:59:43 +00:00
|
|
|
}
|
|
|
|
|
2005-01-15 09:01:52 +00:00
|
|
|
if (option_verbose > 2) {
|
|
|
|
ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: dsn is %s\n",dsn);
|
2005-06-06 02:43:01 +00:00
|
|
|
if (username)
|
|
|
|
{
|
|
|
|
ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: username is %s\n",username);
|
|
|
|
ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: password is [secret]\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: retreiving username and password from odbc config\n");
|
2005-01-15 09:01:52 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: table is %s\n",table);
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
|
|
|
|
2003-12-07 06:43:30 +00:00
|
|
|
res = odbc_init();
|
2004-10-05 01:05:30 +00:00
|
|
|
if (res < 0) {
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_log(LOG_ERROR, "cdr_odbc: Unable to connect to datasource: %s\n", dsn);
|
2005-01-15 09:01:52 +00:00
|
|
|
if (option_verbose > 2) {
|
|
|
|
ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: Unable to connect to datasource: %s\n", dsn);
|
|
|
|
}
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
2006-08-21 02:11:39 +00:00
|
|
|
res = ast_cdr_register(name, ast_module_info->description, odbc_log);
|
2004-10-05 01:05:30 +00:00
|
|
|
if (res) {
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_log(LOG_ERROR, "cdr_odbc: Unable to register ODBC CDR handling\n");
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
2004-01-04 05:11:53 +00:00
|
|
|
out:
|
2006-10-23 00:27:39 +00:00
|
|
|
if (cfg)
|
|
|
|
ast_config_destroy(cfg);
|
2003-12-24 00:04:33 +00:00
|
|
|
ast_mutex_unlock(&odbc_lock);
|
2003-12-02 00:27:28 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2003-12-24 00:04:33 +00:00
|
|
|
static int odbc_do_query(void)
|
2003-12-02 00:27:28 +00:00
|
|
|
{
|
2003-12-24 00:04:33 +00:00
|
|
|
int ODBC_res;
|
2003-12-02 00:27:28 +00:00
|
|
|
ODBC_res = SQLExecute(ODBC_stmt);
|
2004-10-05 01:05:30 +00:00
|
|
|
|
|
|
|
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
|
|
|
|
if (option_verbose > 10)
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error in Query %d\n", ODBC_res);
|
2003-12-02 00:27:28 +00:00
|
|
|
return -1;
|
2004-10-05 01:05:30 +00:00
|
|
|
} else {
|
|
|
|
if (option_verbose > 10)
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query Successful!\n");
|
2003-12-02 00:27:28 +00:00
|
|
|
connected = 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-12-07 17:12:39 +00:00
|
|
|
static int odbc_init(void)
|
2003-12-02 00:27:28 +00:00
|
|
|
{
|
2003-12-24 00:04:33 +00:00
|
|
|
int ODBC_res;
|
2003-12-02 00:27:28 +00:00
|
|
|
|
2004-10-05 01:05:30 +00:00
|
|
|
if (ODBC_env == SQL_NULL_HANDLE || connected == 0) {
|
2003-12-02 00:27:28 +00:00
|
|
|
ODBC_res = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &ODBC_env);
|
2004-10-05 01:05:30 +00:00
|
|
|
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
|
|
|
|
if (option_verbose > 10)
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error AllocHandle\n");
|
2003-12-02 00:27:28 +00:00
|
|
|
connected = 0;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ODBC_res = SQLSetEnvAttr(ODBC_env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
|
|
|
|
|
2004-10-05 01:05:30 +00:00
|
|
|
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
|
|
|
|
if (option_verbose > 10)
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error SetEnv\n");
|
2003-12-02 00:27:28 +00:00
|
|
|
SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
|
This patch is relevant to:
ABE-1628 and RYM-150398 and AST-103 in internal Digium
bug trackers.
These fixes address a really subtle memory corruption
problem that would happen in machines heavily loaded
in production environments. The corruption would
always take the form of the STMT object getting
nulled out and one of the unixODBC calls would
crash trying to access statement->connection.
It isn't fully proven yet, but the server has
now been running 2.5 days without appreciable
memory growth, or any gain of %cpu, and no
crashes. Whether this is the problem or not
on that server, these fixes are still warranted.
As it turns out, **I** introduced these errors
unwittingly, when I corrected another crash earlier.
I had formed the build_query routine, and failed
to remove mutex_unlock calls in 3 places in the
transplanted code. These unlocks would only
happen in error situations, but unlocking the
mutex early set the code up for a catastrophic
failure, it appears. It would happen only once
every 100K-200K or more calls, under heavy load...
but that is enough.
If another crash occurs, with the same MO,
I'll come back and remove my confession from the log, and
we'll keep searching, but the fact that we
have Asterisk dying from an asynchronous
wiping of the STMT object, only on some connection
error, and that the server has lived for 2.5
days on this code without a crash, sure make
it look like this was the problem!
Also, in several points, Statement handles are
set to NULL after SQLFreeHandle. This was mainly
for insurance, to guarantee a crash. As it turns
out, the code does not appear to be attempting
to use these freed pointers.
Asterisk owes a debt of gratitude to Federico Alves
and Frediano Ziglio for their untiring efforts in
finding this bug, among others.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@150056 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-10-16 15:26:10 +00:00
|
|
|
ODBC_env = SQL_NULL_HANDLE;
|
2003-12-02 00:27:28 +00:00
|
|
|
connected = 0;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ODBC_res = SQLAllocHandle(SQL_HANDLE_DBC, ODBC_env, &ODBC_con);
|
|
|
|
|
2004-10-05 01:05:30 +00:00
|
|
|
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
|
|
|
|
if (option_verbose > 10)
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error AllocHDB %d\n", ODBC_res);
|
2003-12-02 00:27:28 +00:00
|
|
|
SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
|
This patch is relevant to:
ABE-1628 and RYM-150398 and AST-103 in internal Digium
bug trackers.
These fixes address a really subtle memory corruption
problem that would happen in machines heavily loaded
in production environments. The corruption would
always take the form of the STMT object getting
nulled out and one of the unixODBC calls would
crash trying to access statement->connection.
It isn't fully proven yet, but the server has
now been running 2.5 days without appreciable
memory growth, or any gain of %cpu, and no
crashes. Whether this is the problem or not
on that server, these fixes are still warranted.
As it turns out, **I** introduced these errors
unwittingly, when I corrected another crash earlier.
I had formed the build_query routine, and failed
to remove mutex_unlock calls in 3 places in the
transplanted code. These unlocks would only
happen in error situations, but unlocking the
mutex early set the code up for a catastrophic
failure, it appears. It would happen only once
every 100K-200K or more calls, under heavy load...
but that is enough.
If another crash occurs, with the same MO,
I'll come back and remove my confession from the log, and
we'll keep searching, but the fact that we
have Asterisk dying from an asynchronous
wiping of the STMT object, only on some connection
error, and that the server has lived for 2.5
days on this code without a crash, sure make
it look like this was the problem!
Also, in several points, Statement handles are
set to NULL after SQLFreeHandle. This was mainly
for insurance, to guarantee a crash. As it turns
out, the code does not appear to be attempting
to use these freed pointers.
Asterisk owes a debt of gratitude to Federico Alves
and Frediano Ziglio for their untiring efforts in
finding this bug, among others.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@150056 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-10-16 15:26:10 +00:00
|
|
|
ODBC_env = SQL_NULL_HANDLE;
|
2003-12-02 00:27:28 +00:00
|
|
|
connected = 0;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
SQLSetConnectAttr(ODBC_con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)10, 0);
|
|
|
|
}
|
|
|
|
|
2005-07-14 20:08:31 +00:00
|
|
|
/* Note that the username and password could be NULL here, but that is allowed in ODBC.
|
|
|
|
In this case, the default username and password will be used from odbc.conf */
|
2003-12-02 00:27:28 +00:00
|
|
|
ODBC_res = SQLConnect(ODBC_con, (SQLCHAR*)dsn, SQL_NTS, (SQLCHAR*)username, SQL_NTS, (SQLCHAR*)password, SQL_NTS);
|
|
|
|
|
2004-10-05 01:05:30 +00:00
|
|
|
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
|
|
|
|
if (option_verbose > 10)
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error SQLConnect %d\n", ODBC_res);
|
2006-04-19 18:56:38 +00:00
|
|
|
SQLFreeHandle(SQL_HANDLE_DBC, ODBC_con);
|
This patch is relevant to:
ABE-1628 and RYM-150398 and AST-103 in internal Digium
bug trackers.
These fixes address a really subtle memory corruption
problem that would happen in machines heavily loaded
in production environments. The corruption would
always take the form of the STMT object getting
nulled out and one of the unixODBC calls would
crash trying to access statement->connection.
It isn't fully proven yet, but the server has
now been running 2.5 days without appreciable
memory growth, or any gain of %cpu, and no
crashes. Whether this is the problem or not
on that server, these fixes are still warranted.
As it turns out, **I** introduced these errors
unwittingly, when I corrected another crash earlier.
I had formed the build_query routine, and failed
to remove mutex_unlock calls in 3 places in the
transplanted code. These unlocks would only
happen in error situations, but unlocking the
mutex early set the code up for a catastrophic
failure, it appears. It would happen only once
every 100K-200K or more calls, under heavy load...
but that is enough.
If another crash occurs, with the same MO,
I'll come back and remove my confession from the log, and
we'll keep searching, but the fact that we
have Asterisk dying from an asynchronous
wiping of the STMT object, only on some connection
error, and that the server has lived for 2.5
days on this code without a crash, sure make
it look like this was the problem!
Also, in several points, Statement handles are
set to NULL after SQLFreeHandle. This was mainly
for insurance, to guarantee a crash. As it turns
out, the code does not appear to be attempting
to use these freed pointers.
Asterisk owes a debt of gratitude to Federico Alves
and Frediano Ziglio for their untiring efforts in
finding this bug, among others.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@150056 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-10-16 15:26:10 +00:00
|
|
|
ODBC_con = SQL_NULL_HANDLE;
|
2003-12-02 00:27:28 +00:00
|
|
|
SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
|
This patch is relevant to:
ABE-1628 and RYM-150398 and AST-103 in internal Digium
bug trackers.
These fixes address a really subtle memory corruption
problem that would happen in machines heavily loaded
in production environments. The corruption would
always take the form of the STMT object getting
nulled out and one of the unixODBC calls would
crash trying to access statement->connection.
It isn't fully proven yet, but the server has
now been running 2.5 days without appreciable
memory growth, or any gain of %cpu, and no
crashes. Whether this is the problem or not
on that server, these fixes are still warranted.
As it turns out, **I** introduced these errors
unwittingly, when I corrected another crash earlier.
I had formed the build_query routine, and failed
to remove mutex_unlock calls in 3 places in the
transplanted code. These unlocks would only
happen in error situations, but unlocking the
mutex early set the code up for a catastrophic
failure, it appears. It would happen only once
every 100K-200K or more calls, under heavy load...
but that is enough.
If another crash occurs, with the same MO,
I'll come back and remove my confession from the log, and
we'll keep searching, but the fact that we
have Asterisk dying from an asynchronous
wiping of the STMT object, only on some connection
error, and that the server has lived for 2.5
days on this code without a crash, sure make
it look like this was the problem!
Also, in several points, Statement handles are
set to NULL after SQLFreeHandle. This was mainly
for insurance, to guarantee a crash. As it turns
out, the code does not appear to be attempting
to use these freed pointers.
Asterisk owes a debt of gratitude to Federico Alves
and Frediano Ziglio for their untiring efforts in
finding this bug, among others.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@150056 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-10-16 15:26:10 +00:00
|
|
|
ODBC_env = SQL_NULL_HANDLE;
|
2003-12-02 00:27:28 +00:00
|
|
|
connected = 0;
|
|
|
|
return -1;
|
2004-10-05 01:05:30 +00:00
|
|
|
} else {
|
|
|
|
if (option_verbose > 10)
|
2003-12-07 06:43:30 +00:00
|
|
|
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Connected to %s\n", dsn);
|
2003-12-02 00:27:28 +00:00
|
|
|
connected = 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-08-21 02:11:39 +00:00
|
|
|
static int load_module(void)
|
2003-12-02 00:27:28 +00:00
|
|
|
{
|
2003-12-07 06:43:30 +00:00
|
|
|
return odbc_load_module();
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
|
|
|
|
2006-08-21 02:11:39 +00:00
|
|
|
static int unload_module(void)
|
2003-12-02 00:27:28 +00:00
|
|
|
{
|
2003-12-07 06:43:30 +00:00
|
|
|
return odbc_unload_module();
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
|
|
|
|
2006-08-21 02:11:39 +00:00
|
|
|
static int reload(void)
|
2003-12-02 00:27:28 +00:00
|
|
|
{
|
2003-12-07 06:43:30 +00:00
|
|
|
odbc_unload_module();
|
|
|
|
return odbc_load_module();
|
2003-12-02 00:27:28 +00:00
|
|
|
}
|
|
|
|
|
2006-08-21 02:11:39 +00:00
|
|
|
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ODBC CDR Backend",
|
|
|
|
.load = load_module,
|
|
|
|
.unload = unload_module,
|
|
|
|
.reload = reload,
|
|
|
|
);
|