dbase.c

来自「性能优秀的SIP Proxy」· C语言 代码 · 共 746 行 · 第 1/2 页

C
746
字号
/* * $Id: dbase.c,v 1.7 2006/05/24 08:53:33 bogdan_iancu Exp $ * * UNIXODBC module core functions * * Copyright (C) 2005-2006 Marco Lorrai * * This file is part of openser, a free SIP server. * * openser is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * openser is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * * History: * -------- *  2005-12-01  initial commit (chgen) *  2006-04-03  fixed invalid handle to extract error (sgupta) *  2006-04-04  removed deprecated ODBC functions, closed cursors on error *              (sgupta) *  2006-05-05  Fixed reconnect code to actually work on connection loss  *              (sgupta) */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <time.h>#include "../../mem/mem.h"#include "../../dprint.h"#include "../../db/db_pool.h"#include "utils.h"#include "val.h"#include "my_con.h"#include "res.h"#include "db_mod.h"#include "dbase.h"#define SQL_BUF_LEN 65536static char sql_buf[SQL_BUF_LEN];/* * Reconnect if connection is broken */static int reconnect(db_con_t* _h, const char* _s){	int ret = 0;	SQLCHAR outstr[1024];	SQLSMALLINT outstrlen;	char conn_str[MAX_CONN_STR_LEN];	LOG(L_ERR, "ERROR:unixodbc:reconnect: Attempting DB reconnect\n");	/* Disconnect */	SQLDisconnect (CON_CONNECTION(_h));	/* Reconnect */	if (!build_conn_str(CON_ID(_h), conn_str)) {		LOG(L_ERR, "ERROR:unixodbc:reconnect: failed to build "			"connection string\n");		return ret;	}	ret = SQLDriverConnect(CON_CONNECTION(_h), (void *)1,			(SQLCHAR*)conn_str, SQL_NTS, outstr, sizeof(outstr),			&outstrlen, SQL_DRIVER_COMPLETE);	if (!SQL_SUCCEEDED(ret)) {		LOG(L_ERR, "ERROR:unixodbc:reconnect: failed to connect\n");		extract_error("SQLDriverConnect", CON_CONNECTION(_h),			SQL_HANDLE_DBC, NULL);		return ret;	}	ret = SQLAllocHandle(SQL_HANDLE_STMT, CON_CONNECTION(_h),			&CON_RESULT(_h));	if (!SQL_SUCCEEDED(ret)) {		LOG(L_ERR, "ERROR:unixodbc:reconnect: Statement allocation "			"error %d\n", (int)(long)CON_CONNECTION(_h));		extract_error("SQLAllocStmt", CON_CONNECTION(_h), SQL_HANDLE_DBC,NULL);		return ret;	}	return ret;}/* * Send an SQL query to the server */static int submit_query(db_con_t* _h, const char* _s){	int ret = 0;	SQLCHAR sqlstate[7];	/* first do some cleanup if required */	if(CON_RESULT(_h))	{		SQLCloseCursor(CON_RESULT(_h));		SQLFreeHandle(SQL_HANDLE_STMT, CON_RESULT(_h));	}	ret = SQLAllocHandle(SQL_HANDLE_STMT, CON_CONNECTION(_h), &CON_RESULT(_h));	if (!SQL_SUCCEEDED(ret))	{		LOG(L_ERR, "ERROR:unixodbc:submit_query: Statement allocation "			"error %d\n", (int)(long)CON_CONNECTION(_h));		extract_error("SQLAllocStmt", CON_CONNECTION(_h), SQL_HANDLE_DBC,			(char*)sqlstate);				/* Connection broken */		if( !strncmp((char*)sqlstate,"08003",5) ||		!strncmp((char*)sqlstate,"08S01",5) ) {			ret = reconnect(_h, _s);			if( !SQL_SUCCEEDED(ret) ) return ret;		} else {			return ret;		}	}	ret=SQLExecDirect(CON_RESULT(_h),  (SQLCHAR*)_s, SQL_NTS);	if (!SQL_SUCCEEDED(ret))	{		SQLCHAR sqlstate[7];		LOG(L_ERR, "unixodbc:SQLExecDirect, rv=%d. Query= %s\n", ret, _s);		extract_error("SQLExecDirect", CON_RESULT(_h), SQL_HANDLE_STMT,			(char*)sqlstate);		/* Connection broken */		if( !strncmp((char*)sqlstate,"08003",5) ||		    !strncmp((char*)sqlstate,"08S01",5) 		    )		{			ret = reconnect(_h, _s);			if( SQL_SUCCEEDED(ret) ) {				/* Try again */				ret=SQLExecDirect(CON_RESULT(_h),  (SQLCHAR*)_s, SQL_NTS);				if (!SQL_SUCCEEDED(ret)) {					LOG(L_ERR, "unixodbc:SQLExecDirect, rv=%d. Query= %s\n",						ret, _s);					extract_error("SQLExecDirect", CON_RESULT(_h),						SQL_HANDLE_STMT, (char*)sqlstate);					/* Close the cursor */					SQLCloseCursor(CON_RESULT(_h));					SQLFreeHandle(SQL_HANDLE_STMT, CON_RESULT(_h));				}			}		}		else {			/* Close the cursor */ 			SQLCloseCursor(CON_RESULT(_h));			SQLFreeHandle(SQL_HANDLE_STMT, CON_RESULT(_h));		}	}	return ret;}/* * Print list of columns separated by comma */static int print_columns(char* _b, int _l, db_key_t* _c, int _n){	int i, ret;	int len = 0;	if ((!_c) || (!_n) || (!_b) || (!_l))	{		LOG(L_ERR, "print_columns: Invalid parameter value\n");		return -1;	}	for(i = 0; i < _n; i++)	{		if (i == (_n - 1))		{			ret = snprintf(_b + len, _l - len, "%s ", _c[i]);			if (ret < 0 || ret >= (_l - len)) goto error;			len += ret;		}		else		{			ret = snprintf(_b + len, _l - len, "%s,", _c[i]);			if (ret < 0 || ret >= (_l - len)) goto error;			len += ret;		}	}	return len;	error:	LOG(L_ERR, "print_columns: Error in snprintf\n");	return -1;}/* * Print list of values separated by comma */static int print_values(SQLHDBC* _c, char* _b, int _l, db_val_t* _v, int _n){	int i, res = 0, l;	if (!_c || !_b || !_l || !_v || !_n)	{		LOG(L_ERR, "print_values: Invalid parameter value\n");		return -1;	}	for(i = 0; i < _n; i++)	{		l = _l - res;		if (val2str(_c, _v + i, _b + res, &l) < 0)		{			LOG(L_ERR, "print_values: Error while converting value to string\n");			return -1;		}		res += l;		if (i != (_n - 1))		{			*(_b + res) = ',';			res++;		}	}	return res;}/* * Print where clause of SQL statement */static int print_where(SQLHDBC* _c, char* _b, int _l, db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n){	int i;	int len = 0, ret;	int l;	if (!_c || !_b || !_l || !_k || !_v || !_n)	{		LOG(L_ERR, "print_where: Invalid parameter value\n");		return -1;	}	for(i = 0; i < _n; i++)	{		if (_o)		{			ret = snprintf(_b + len, _l - len, "%s%s", _k[i], _o[i]);			if (ret < 0 || ret >= (_l - len)) goto error;			len += ret;		}		else		{			ret = snprintf(_b + len, _l - len, "%s=", _k[i]);			if (ret < 0 || ret >= (_l - len)) goto error;			len += ret;		}		l = _l - len;		val2str(_c, &(_v[i]), _b + len, &l);		len += l;		if (i != (_n - 1))		{			ret = snprintf(_b + len, _l - len, " AND ");			if (ret < 0 || ret >= (_l - len)) goto error;			len += ret;		}	}	return len;	error:	LOG(L_ERR, "print_where: Error in snprintf\n");	return -1;}/* * Print set clause of update SQL statement */static int print_set(SQLHDBC* _c, char* _b, int _l, db_key_t* _k, db_val_t* _v, int _n){	int i;	int len = 0, ret;	int l;	if (!_c || !_b || !_l || !_k || !_v || !_n)	{		LOG(L_ERR, "print_set: Invalid parameter value\n");		return -1;	}	for(i = 0; i < _n; i++)	{		ret = snprintf(_b + len, _l - len, "%s=", _k[i]);		if (ret < 0 || ret >= (_l - len)) goto error;		len += ret;		l = _l - len;		val2str(_c, &(_v[i]), _b + len, &l);		len += l;		if (i != (_n - 1))		{			if ((_l - len) >= 1)			{				*(_b + len++) = ',';			}		}	}	return len;	error:	LOG(L_ERR, "print_set: Error in snprintf\n");	return -1;}/* * Initialize database module * No function should be called before this */db_con_t* db_init(const char* _url){	struct db_id* id;	struct my_con* con;	db_con_t* res;	id = 0;	res = 0;	if (!_url)	{		LOG(L_ERR, "db_init: Invalid parameter value\n");		return 0;	}	res = pkg_malloc(sizeof(db_con_t) + sizeof(struct my_con*));	if (!res)	{		LOG(L_ERR, "db_init: No memory left\n");		return 0;	}	memset(res, 0, sizeof(db_con_t) + sizeof(struct my_con*));	id = new_db_id(_url);	if (!id)	{		LOG(L_ERR, "db_init: Cannot parse URL '%s'\n", _url);		goto err;	}/* Find the connection in the pool */	con = (struct my_con*)pool_get(id);	if (!con)	{		DBG("db_init: Connection '%s' not found in pool\n", _url);/* Not in the pool yet */		con = new_connection(id);		if (!con)		{			goto err;		}		pool_insert((struct pool_con*)con);	}	else	{		DBG("db_init: Connection '%s' found in pool\n", _url);	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?