refactor switch_core_sql_thread with the following main changes:

Do the entire transaction as a single exec, instead of 3 separate ones to resolve issue of unmatched transaction error.
try really hard to commit the transaction (1000 times) but we no longer try forever.  If 1000 times fail, you will lose some update/insert/deletes from the core db, but we will no longer continue to loop forever and stop processing the sql queue in the case of an error.
added better overflow protection to the buffer, we now ignore sql strings we get over 64k. (not full transactions, just individual sql strings that we get queued).  Previously this caused a buffer overflow.
We now use sprintf instead of snprintf as we are already handling overflow checks outside of the sprintf.


git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@4338 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Michael Jerris 2007-02-20 18:27:21 +00:00
parent 9e8a2b3e07
commit e4947bfbfe

View File

@ -3790,9 +3790,15 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread,
uint32_t itterations = 0;
uint8_t trans = 0, nothing_in_queue = 0;
uint32_t freq = 1000, target = 1000;
uint32_t len = 0;
uint32_t sql_len = SQLLEN;
switch_size_t len = 0, sql_len = SQLLEN;
const char *begin_sql = "BEGIN DEFERRED TRANSACTION CORE1;\n";
char *end_sql = "END TRANSACTION CORE1";
switch_size_t begin_len = strlen(begin_sql);
switch_size_t end_len = strlen(end_sql);
char *sqlbuf = (char *) malloc(sql_len);
char *sql;
switch_size_t newlen;
if (!runtime.event_db) {
runtime.event_db = switch_core_db_handle();
@ -3801,28 +3807,32 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread,
for(;;) {
if (switch_queue_trypop(runtime.sql_queue, &pop) == SWITCH_STATUS_SUCCESS) {
char *sql = (char *) pop;
uint32_t newlen;
sql = (char *) pop;
if (sql) {
if (itterations == 0) {
char *isql = "begin transaction CORE1;\n";
switch_core_db_persistant_execute(runtime.event_db, isql, 0);
trans = 1;
newlen = strlen(sql) + 2;
/* ignore abnormally large strings sql strings as potential buffer overflow */
if (newlen + end_len < SQLLEN) {
if (itterations == 0) {
len = begin_len;
sprintf(sqlbuf, "%s", begin_sql);
trans = 1;
}
itterations++;
newlen = (uint32_t)strlen(sql) + 2;
if (len + newlen > sql_len) {
if (len + newlen + end_len > sql_len) {
sql_len = len + SQLLEN;
if (!(sqlbuf = realloc(sqlbuf, sql_len))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL thread ending on mem err\n");
break;
}
}
snprintf(sqlbuf + len, sql_len - len, "%s;\n", sql);
sprintf(sqlbuf + len, "%s;\n", sql);
len += newlen;
}
switch_core_db_free(sql);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "SQL thread ending\n");
@ -3834,10 +3844,10 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread,
if (trans && ((itterations == target) || nothing_in_queue)) {
char *isql = "end transaction CORE1";
switch_core_db_persistant_execute(runtime.event_db, sqlbuf, 0);
switch_core_db_persistant_execute(runtime.event_db, isql, 0);
sprintf(sqlbuf + len, "%s", end_sql);
if (switch_core_db_persistant_execute(runtime.event_db, sqlbuf, 1000) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL thread unable to commit transaction, records lost!\n");
}
itterations = 0;
trans = 0;
nothing_in_queue = 0;