ソースを参照

proposed change for dbtext query results.
this behaviour was observed by interacting with module presence.

presentity clean runs from timer every 6 secs.
if the first run returns a large set of rows, it iterates all rows doing
some notifications and deleting the presentity.
if it takes more then 6 secs to complete, the next run will override the
results internal structure pointer maintained in the connection level.

the proposed patch, maintains the query result internal structure within
the result, using the ptr field for that.

Luis Azedo 11 年 前
コミット
dae74e974a

+ 40 - 46
modules/db_text/dbt_api.c

@@ -44,16 +44,16 @@ int dbt_use_table(db1_con_t* _h, const str* _t)
 /*
  * Get and convert columns from a result
  */
-static int dbt_get_columns(db1_con_t* _h, db1_res_t* _r)
+static int dbt_get_columns(db1_res_t* _r, dbt_result_p _dres)
 {
 	int col;
 	
-	if (!_h || !_r) {
+	if (!_r || !_dres) {
 		LM_ERR("invalid parameter\n");
 		return -1;
 	}
 	
-	RES_COL_N(_r) = DBT_CON_RESULT(_h)->nrcols;
+	RES_COL_N(_r) = _dres->nrcols;
 	if (!RES_COL_N(_r)) {
 		LM_ERR("no columns\n");
 		return -2;
@@ -78,10 +78,10 @@ static int dbt_get_columns(db1_con_t* _h, db1_res_t* _r)
 		LM_DBG("allocate %d bytes for RES_NAMES[%d] at %p",
 				(int)sizeof(str), col,
 				RES_NAMES(_r)[col]);
-		RES_NAMES(_r)[col]->s = DBT_CON_RESULT(_h)->colv[col].name.s;
-		RES_NAMES(_r)[col]->len = DBT_CON_RESULT(_h)->colv[col].name.len;
+		RES_NAMES(_r)[col]->s = _dres->colv[col].name.s;
+		RES_NAMES(_r)[col]->len = _dres->colv[col].name.len;
 
-		switch(DBT_CON_RESULT(_h)->colv[col].type)
+		switch(_dres->colv[col].type)
 		{
 			case DB1_STR:
 			case DB1_STRING:
@@ -89,12 +89,12 @@ static int dbt_get_columns(db1_con_t* _h, db1_res_t* _r)
 			case DB1_INT:
 			case DB1_DATETIME:
 			case DB1_DOUBLE:
-				RES_TYPES(_r)[col] = DBT_CON_RESULT(_h)->colv[col].type;
+				RES_TYPES(_r)[col] = _dres->colv[col].type;
 			break;
 			default:
 				LM_WARN("unhandled data type column (%.*s) type id (%d), "
 						"use STR as default\n", RES_NAMES(_r)[col]->len,
-						RES_NAMES(_r)[col]->s, DBT_CON_RESULT(_h)->colv[col].type);
+						RES_NAMES(_r)[col]->s, _dres->colv[col].type);
 				RES_TYPES(_r)[col] = DB1_STR;
 			break;
 		}
@@ -105,10 +105,10 @@ static int dbt_get_columns(db1_con_t* _h, db1_res_t* _r)
 /*
  * Convert a row from result into db API representation
  */
-static int dbt_convert_row(db1_con_t* _h, db1_res_t* _res, db_row_t* _r)
+static int dbt_convert_row(db1_res_t* _res, db_row_t* _r, dbt_row_p _r1)
 {
 	int i;
-	if (!_h || !_r || !_res) {
+	if (!_r || !_res || !_r1) {
 		LM_ERR("invalid parameter value\n");
 		return -1;
 	}
@@ -119,12 +119,12 @@ static int dbt_convert_row(db1_con_t* _h, db1_res_t* _res, db_row_t* _r)
 	}
 
 	for(i = 0; i < RES_COL_N(_res); i++) {
-		(ROW_VALUES(_r)[i]).nul = DBT_CON_ROW(_h)->fields[i].nul;
+		(ROW_VALUES(_r)[i]).nul = _r1->fields[i].nul;
 		switch(RES_TYPES(_res)[i])
 		{
 			case DB1_INT:
 				VAL_INT(&(ROW_VALUES(_r)[i])) = 
-						DBT_CON_ROW(_h)->fields[i].val.int_val;
+						_r1->fields[i].val.int_val;
 				VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB1_INT;
 			break;
 
@@ -134,46 +134,46 @@ static int dbt_convert_row(db1_con_t* _h, db1_res_t* _res, db_row_t* _r)
 
 			case DB1_DOUBLE:
 				VAL_DOUBLE(&(ROW_VALUES(_r)[i])) = 
-						DBT_CON_ROW(_h)->fields[i].val.double_val;
+						_r1->fields[i].val.double_val;
 				VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB1_DOUBLE;
 			break;
 
 			case DB1_STRING:
 				VAL_STR(&(ROW_VALUES(_r)[i])).s = 
-						DBT_CON_ROW(_h)->fields[i].val.str_val.s;
+						_r1->fields[i].val.str_val.s;
 				VAL_STR(&(ROW_VALUES(_r)[i])).len =
-						DBT_CON_ROW(_h)->fields[i].val.str_val.len;
+						_r1->fields[i].val.str_val.len;
 				VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB1_STRING;
 				VAL_FREE(&(ROW_VALUES(_r)[i])) = 0;
 			break;
 
 			case DB1_STR:
 				VAL_STR(&(ROW_VALUES(_r)[i])).s = 
-						DBT_CON_ROW(_h)->fields[i].val.str_val.s;
+						_r1->fields[i].val.str_val.s;
 				VAL_STR(&(ROW_VALUES(_r)[i])).len =
-						DBT_CON_ROW(_h)->fields[i].val.str_val.len;
+						_r1->fields[i].val.str_val.len;
 				VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB1_STR;
 				VAL_FREE(&(ROW_VALUES(_r)[i])) = 0;
 			break;
 
 			case DB1_DATETIME:
 				VAL_INT(&(ROW_VALUES(_r)[i])) = 
-						DBT_CON_ROW(_h)->fields[i].val.int_val;
+						_r1->fields[i].val.int_val;
 				VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB1_DATETIME;
 			break;
 
 			case DB1_BLOB:
 				VAL_STR(&(ROW_VALUES(_r)[i])).s =
-						DBT_CON_ROW(_h)->fields[i].val.str_val.s;
+						_r1->fields[i].val.str_val.s;
 				VAL_STR(&(ROW_VALUES(_r)[i])).len =
-						DBT_CON_ROW(_h)->fields[i].val.str_val.len;
+						_r1->fields[i].val.str_val.len;
 				VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB1_BLOB;
 				VAL_FREE(&(ROW_VALUES(_r)[i])) = 0;
 			break;
 
 			case DB1_BITMAP:
 				VAL_INT(&(ROW_VALUES(_r)[i])) =
-					DBT_CON_ROW(_h)->fields[i].val.bitmap_val;
+						_r1->fields[i].val.bitmap_val;
 				VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB1_INT;
 			break;
 
@@ -189,15 +189,15 @@ static int dbt_convert_row(db1_con_t* _h, db1_res_t* _res, db_row_t* _r)
 /*
  * Convert rows from internal to db API representation
  */
-static int dbt_convert_rows(db1_con_t* _h, db1_res_t* _r)
+static int dbt_convert_rows(db1_res_t* _r, dbt_result_p _dres)
 {
-	int col;
+	int row;
 	dbt_row_p _rp = NULL;
-	if (!_h || !_r) {
+	if (!_r || !_dres) {
 		LM_ERR("invalid parameter\n");
 		return -1;
 	}
-	RES_ROW_N(_r) = DBT_CON_RESULT(_h)->nrrows;
+	RES_ROW_N(_r) = _dres->nrrows;
 	if (!RES_ROW_N(_r)) {
 		return 0;
 	}
@@ -205,23 +205,16 @@ static int dbt_convert_rows(db1_con_t* _h, db1_res_t* _r)
 		LM_ERR("could not allocate rows");
 		return -2;
 	}
-	col = 0;
-	_rp = DBT_CON_RESULT(_h)->rows;
+	row = 0;
+	_rp = _dres->rows;
 	while(_rp) {
-		DBT_CON_ROW(_h) = _rp;
-		if (!DBT_CON_ROW(_h)) {
-			LM_ERR("failed to get current row\n");
-			RES_ROW_N(_r) = col;
-			db_free_rows(_r);
-			return -3;
-		}
-		if (dbt_convert_row(_h, _r, &(RES_ROWS(_r)[col])) < 0) {
-			LM_ERR("failed to convert row #%d\n", col);
-			RES_ROW_N(_r) = col;
+		if (dbt_convert_row(_r, &(RES_ROWS(_r)[row]), _rp) < 0) {
+			LM_ERR("failed to convert row #%d\n", row);
+			RES_ROW_N(_r) = row;
 			db_free_rows(_r);
 			return -4;
 		}
-		col++;
+		row++;
 		_rp = _rp->next;
 	}
 	return 0;
@@ -231,18 +224,18 @@ static int dbt_convert_rows(db1_con_t* _h, db1_res_t* _r)
 /*
  * Fill the structure with data from database
  */
-static int dbt_convert_result(db1_con_t* _h, db1_res_t* _r)
+static int dbt_convert_result(db1_res_t* _r, dbt_result_p _dres)
 {
-	if (!_h || !_r) {
+	if (!_r || !_dres) {
 		LM_ERR("invalid parameter\n");
 		return -1;
 	}
-	if (dbt_get_columns(_h, _r) < 0) {
+	if (dbt_get_columns(_r, _dres) < 0) {
 		LM_ERR("failed to get column names\n");
 		return -2;
 	}
 
-	if (dbt_convert_rows(_h, _r) < 0) {
+	if (dbt_convert_rows(_r, _dres) < 0) {
 		LM_ERR("failed to convert rows\n");
 		db_free_columns(_r);
 		return -3;
@@ -253,14 +246,14 @@ static int dbt_convert_result(db1_con_t* _h, db1_res_t* _r)
 /*
  * Retrieve result set
  */
-int dbt_get_result(db1_con_t* _h, db1_res_t** _r)
+int dbt_get_result(db1_res_t** _r, dbt_result_p _dres)
 {
-	if (!_h || !_r) {
+	if ( !_r) {
 		LM_ERR("invalid parameter value\n");
 		return -1;
 	}
 
-	if (!DBT_CON_RESULT(_h))
+	if (!_dres)
 	{
 		LM_ERR("failed to get result\n");
 		*_r = 0;
@@ -274,12 +267,13 @@ int dbt_get_result(db1_con_t* _h, db1_res_t** _r)
 		return -2;
 	}
 
-	if (dbt_convert_result(_h, *_r) < 0) 
+	if (dbt_convert_result(*_r, _dres) < 0)
 	{
 		LM_ERR("failed to convert result\n");
 		pkg_free(*_r);
 		return -4;
 	}
 	
+	(*_r)->ptr = _dres;
 	return 0;
 }

+ 2 - 1
modules/db_text/dbt_api.h

@@ -36,10 +36,11 @@
 #include "../../lib/srdb1/db_con.h"
 #include "../../lib/srdb1/db_row.h"
 
+#include "dbt_res.h"
 /*
  * Retrieve result set
  */
-int dbt_get_result(db1_con_t* _h, db1_res_t** _r);
+int dbt_get_result(db1_res_t** _r, dbt_result_p _dres);
 
 int dbt_use_table(db1_con_t* _h, const str* _t);
 

+ 14 - 13
modules/db_text/dbt_base.c

@@ -119,9 +119,6 @@ void dbt_close(db1_con_t* _h)
 		return;
 	}
 	
-	if (DBT_CON_RESULT(_h)) 
-		dbt_result_free(DBT_CON_RESULT(_h));
-	
 	pkg_free(_h);
     return;
 }
@@ -138,19 +135,18 @@ int dbt_free_result(db1_con_t* _h, db1_res_t* _r)
 		return -1;
 	}
 
-	if(db_free_result(_r) < 0) 
+
+	if(dbt_result_free((dbt_result_p)_r->ptr) < 0)
 	{
-		LM_ERR("unable to free result structure\n");
-		return -1;
+		LM_ERR("unable to free internal structure\n");
 	}
 
-	
-	if(dbt_result_free(DBT_CON_RESULT(_h)) < 0) 
+	if(db_free_result(_r) < 0) 
 	{
-		LM_ERR("unable to free internal structure\n");
+		LM_ERR("unable to free result structure\n");
 		return -1;
 	}
-	DBT_CON_RESULT(_h) = NULL;
+
 	return 0;
 }
 
@@ -173,6 +169,7 @@ int dbt_query(db1_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v,
 	dbt_table_p _tbc = NULL;
 	dbt_row_p _drp = NULL;
 	dbt_result_p _dres = NULL;
+	int result = 0;
 	
 	int *lkey=NULL, *lres=NULL;
 	
@@ -273,8 +270,6 @@ int dbt_query(db1_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v,
 
 	/* dbt_result_print(_dres); */
 	
-	DBT_CON_RESULT(_h) = _dres;
-	
 	if(lkey)
 		pkg_free(lkey);
 	if(lres)
@@ -286,7 +281,11 @@ int dbt_query(db1_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v,
  	if(_o_l)
  		pkg_free(_o_l);
 
-	return dbt_get_result(_h, _r);
+	result = dbt_get_result(_r, _dres);
+	if(result != 0)
+		dbt_result_free(_dres);
+
+	return result;
 
 error:
 	/* unlock database */
@@ -302,6 +301,8 @@ error_nounlock:
 		pkg_free(_o_op);
 	if(_o_l)
 		pkg_free(_o_l);
+	if(_dres)
+		dbt_result_free(_dres);
 	LM_ERR("failed to query the table!\n");
 
 	return -1;

+ 3 - 1
modules/db_text/dbt_res.c

@@ -119,7 +119,9 @@ int dbt_result_free(dbt_result_p _dres)
 			for(i=0; i<_dres->nrcols; i++)
 			{
 				if((_dres->colv[i].type==DB1_STR 
-							|| _dres->colv[i].type==DB1_STRING)
+							|| _dres->colv[i].type==DB1_STRING
+							|| _dres->colv[i].type==DB1_BLOB
+							)
 						&& _rp0->fields[i].val.str_val.s)
 					pkg_free(_rp0->fields[i].val.str_val.s);
 			}

+ 0 - 6
modules/db_text/dbt_res.h

@@ -44,18 +44,12 @@ typedef struct _dbt_result
 	dbt_row_p rows;
 } dbt_result_t, *dbt_result_p;
 
-//typedef db1_res_t dbt_result_t, *dbt_result_p;
-
 typedef struct _dbt_con
 {
 	dbt_cache_p con;
-	dbt_result_p res;
-	dbt_row_p row;
 } dbt_con_t, *dbt_con_p;
 
 #define DBT_CON_CONNECTION(db_con) (((dbt_con_p)((db_con)->tail))->con)
-#define DBT_CON_RESULT(db_con)     (((dbt_con_p)((db_con)->tail))->res)
-#define DBT_CON_ROW(db_con)        (((dbt_con_p)((db_con)->tail))->row)
 
 dbt_result_p dbt_result_new(dbt_table_p, int*, int);
 int dbt_result_free(dbt_result_p);