Skip to content

Commit

Permalink
db_unixodbc: fix query result handling and improve performance
Browse files Browse the repository at this point in the history
Until now, query rows were incrementally stored in a list with
separately allocated length and string buffers, along with a great deal
of useless pointer dereferencing, effectively wasting CPU cycles and pkg
mem usage.

This patch eliminates the linked list logic with a global buffer of
pointers (doubling in size when required) meant to hold each result column.
Each column is transparently freed by the DB backend. This completes
commit d63ee19.
(cherry picked from commit 683dfaa)
  • Loading branch information
liviuchircu committed Oct 15, 2014
1 parent fb13b39 commit e0c1fea
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 248 deletions.
2 changes: 0 additions & 2 deletions modules/db_unixodbc/con.h
Expand Up @@ -60,7 +60,6 @@ struct my_con
SQLHSTMT stmt_handle; /* Actual result */
SQLHDBC dbc; /* Connection representation */
char** row; /* Actual row in the result */
void *data;
time_t timestamp; /* Timestamp of last query */
};

Expand All @@ -73,7 +72,6 @@ struct my_con
#define CON_TIMESTAMP(db_con) (((struct my_con*)((db_con)->tail))->timestamp)
#define CON_ID(db_con) (((struct my_con*)((db_con)->tail))->id)
#define CON_ENV(db_con) (((struct my_con*)((db_con)->tail))->env)
#define CON_DATA(db_con) (((struct my_con*)((db_con)->tail))->data)

#define MAX_CONN_STR_LEN 2048

Expand Down
8 changes: 2 additions & 6 deletions modules/db_unixodbc/dbase.c
Expand Up @@ -38,7 +38,6 @@
#include "../../dprint.h"
#include "../../db/db_query.h"
#include "val.h"
#include "list.h"
#include "con.h"
#include "res.h"
#include "db_unixodbc.h"
Expand Down Expand Up @@ -247,12 +246,9 @@ int db_unixodbc_free_result(db_con_t* _h, db_res_t* _r)
return -1;
}

/* free the duplicated list of results */
if (CON_DATA(_h))
db_unixodbc_list_destroy((list *)CON_DATA(_h));

SQLFreeHandle(SQL_HANDLE_STMT, CON_RESULT(_h));
CON_RESULT(_h) = 0;
CON_RESULT(_h) = NULL;

return 0;
}

Expand Down
150 changes: 0 additions & 150 deletions modules/db_unixodbc/list.c

This file was deleted.

51 changes: 0 additions & 51 deletions modules/db_unixodbc/list.h

This file was deleted.

47 changes: 16 additions & 31 deletions modules/db_unixodbc/res.c
Expand Up @@ -36,7 +36,6 @@
#include "../../db/db_res.h"
#include "con.h"
#include "res.h"
#include "list.h"
#include <stdlib.h>
#include <string.h>

Expand Down Expand Up @@ -160,9 +159,8 @@ static inline int db_unixodbc_convert_rows(const db_con_t* _h, db_res_t* _r)
{
int row_n = 0, i = 0, ret = 0;
SQLSMALLINT columns;
list* rows = NULL;
list* rowstart = NULL;
strn* temp_row = NULL;
str *rows = NULL;

if((!_h) || (!_r)) {
LM_ERR("invalid parameter\n");
Expand All @@ -173,10 +171,10 @@ static inline int db_unixodbc_convert_rows(const db_con_t* _h, db_res_t* _r)
temp_row = (strn*)pkg_malloc( columns*sizeof(strn) );
if(!temp_row) {
LM_ERR("no private memory left\n");
return -1;
return E_OUT_OF_MEM;
}

while(SQL_SUCCEEDED(ret = SQLFetch(CON_RESULT(_h))))
while (SQL_SUCCEEDED(ret = SQLFetch(CON_RESULT(_h))))
{
for(i=0; i < columns; i++)
{
Expand All @@ -192,52 +190,39 @@ static inline int db_unixodbc_convert_rows(const db_con_t* _h, db_res_t* _r)
}
}

if (db_unixodbc_list_insert(&rowstart, &rows, columns, temp_row) < 0) {
LM_ERR("insert failed\n");
pkg_free(temp_row);
temp_row= NULL;
return -5;
rows = db_unixodbc_dup_row(temp_row, row_n, columns);
if (!rows) {
LM_ERR("no more pkg mem\n");
return E_OUT_OF_MEM;
}

row_n++;
}

/* free temporary row data */
pkg_free(temp_row);
CON_ROW(_h) = NULL;

RES_ROW_N(_r) = row_n;
if (!row_n) {
RES_ROWS(_r) = 0;
if (row_n == 0) {
RES_ROWS(_r) = NULL;
return 0;
}

if (db_allocate_rows( _r, row_n)!=0) {
if (db_allocate_rows(_r, row_n) != 0) {
LM_ERR("no private memory left\n");
return -2;
return E_OUT_OF_MEM;
}

i = 0;
rows = rowstart;
while(rows)
{
CON_ROW(_h) = rows->data;
if (!CON_ROW(_h))
{
LM_ERR("string null\n");
RES_ROW_N(_r) = row_n;
db_free_rows(_r);
return -3;
}
if (db_unixodbc_convert_row(_h, _r, &(RES_ROWS(_r)[i]), rows->lengths) < 0) {
for (i = 0; i < row_n; i++) {
if (db_unixodbc_convert_row(&rows[i * columns], _r, &RES_ROWS(_r)[i]) < 0) {
LM_ERR("converting row failed #%d\n", i);
RES_ROW_N(_r) = i;
RES_ROW_N(_r) = 0;
db_free_rows(_r);
return -4;
}
i++;
rows = rows->next;
}

CON_DATA(_h) = rowstart ? rowstart : NULL;
return 0;
}

Expand Down

0 comments on commit e0c1fea

Please sign in to comment.