现在的位置: 首页 > 综合 > 正文

使用Pro C++实现数据库连接池采用多线程方式访问oracle数据库

2017年12月12日 ⁄ 综合 ⁄ 共 39646字 ⁄ 字号 评论关闭
数据库连接作为一种资源,我们的应用必须对之进行行之有效的管理。我们在访问数据库的时候,一般传统上采用先建立连接,然后使用该连接访问数据库,在使用完毕后,关闭该连接。这是我们经常采用的方法。该方法的好处是使用简单,不用对连接进行任何管理。但随之带来的缺点也就出现了,在应用需要频繁访问数据库的时候,这种方法就会使程序的效率十分低下,甚至有时候是不能满足应用的需要的。随着数据库连接池技术出现了,我们的应用根据访问数据库的频率动态决定创建连接的数量,以及决定在适当的时刻可以关闭一些数据库连接,用以节省这种资源。笔者最近在参考了网上大量代码的同时,实现了如何利用Pro C++使用数据库连接池完成了多线程对oracle数据库的访问。本着来源于网络,共享与网络的精神,和大家共同探讨,其中笔者的大部分代码来源是黄剑锋先生的共享代码,在此深表感谢。实现的基本功能如下:
1:可以设定最小的数据库连接数。
2:可以设定最大的数据库连接数。
3:当数据库某个连接空闲时间多长时间后,该连接池会自动断开连接以节省数据库连接资源。
4:提供了每个连接被使用的次数接口,方便统计和分析各个连接的情况。
5:提供了每个连接从上次访问完毕,懂查看的时候为止,已经空闲的时长,以秒为单位。
6:可以动态访问数据库存储过程,即存储过程的名字可以动态变化的。
 
CConnection:
#pragma once

#include <string>
#include <ace/OS.h>
#include <ace/Task.h>

#define RT_OK   0
#define RT_NG  -1

#define DB_CORE	  0
#define DB_CORE_1 DB_CORE

using namespace std;

/*数据库错误原因*/
#define		RT_CONNECT_FAILED		-2
#define		RT_SOURCE_BUSY 			-3
#define		RT_NO_DATA_FOUND 		-4 		/*when fetch cursor over or cursor is empty*/
#define		RT_DOUBLE_KEY 			-5  	/*unique constraint violated*/
#define		RT_OTHER_ERROR 			-99


/****************************************数据库单连接******************************************/

class CConnection
{
public:
	CConnection();
	CConnection(std::string db_string, std::string db_name);
	virtual ~CConnection();
	void settimerid(int timerid);
	int gettimerid();
	void addinvoke();
	void set(std::string db_string, std::string db_name);
	void set_db_string(std::string db_string);
	void set_db_name(std::string db_name);
	string get_db_string();
	string get_db_name();
	void output();
	void setidletimepoint();
	void* getctctx();
	static int multi_thread();
	int start();
	int stop();
	int connect();
	int disconnect();
	int reconnect();
	bool is_connected();
	/*示例*/
	int DML_DEMO_1();
	int DML_DEMO_2(int i);
	int DML_DEMO_3(int i);
	int DML_DEMO_4(char* inputparam, char* outputparam);
	int DML_DEMO_5(char* spname, char* inputparam, char* outputparam);
private:
	bool db_connected_;
	int  invoke_;
	time_t  idletimepoint_;
	int timerid_;
	/*数据库连接上下文*/
	void * ctx_;
	std::string db_string_; /*数据库连接串 user/pwd@sid*/
	std::string db_name_;   /*数据库连接别名*/
	int SqlError(void *_sqlca, const char *_FunName);
};


/*==================================================================================================
 * 项目名称: Proc++程序模板
 *     功能: 实现Proc预编译程序设计模式
 *     作者: huangjf
 *     联系: huangjf@ffcs.cn
 * 最近修改: 2010-7-15
 *     版本: v2.0.1
 ==================================================================================================*/

#include <list>
#include <vector>
#include <algorithm>
#include <ace/OS.h>
#include <ace/FILE_Addr.h>
#include <ace/FILE_Connector.h>
#include <ace/FILE_IO.h>
#include "Logger.h"
#include "Connection.h"

CConnection::CConnection()
{ 
	CLogger::createinstance()->logdebugmsg("(+)connection address=%08x\n", this);
	db_connected_ = false;
	ctx_ = NULL;
	db_string_ = "NULL";
	db_name_ = "NULL";
	invoke_ = 0;
	idletimepoint_ = time(NULL);
	timerid_ = -1;
}

CConnection::CConnection(std::string db_string, std::string db_name)
{
	CLogger::createinstance()->logdebugmsg("(+)connection address=%08x\n", this);
	db_connected_ = false;
	ctx_ = NULL;
	db_string_ = db_string;
	db_name_ = db_name;
	invoke_ = 0;
	idletimepoint_ = time(NULL);
	timerid_ = -1;
}

CConnection::~CConnection()
{
	CLogger::createinstance()->logdebugmsg("(-)connection address=%08x\n", this);
	db_connected_ = false;
}


void CConnection::settimerid(int timerid)
{
	timerid_ = timerid;
}

int CConnection::gettimerid()
{
	return timerid_;
}

void CConnection::addinvoke()
{
	invoke_++;
}

void CConnection::set(std::string db_string, std::string db_name)
{
	db_string_ = db_string;
	db_name_   = db_name;
}

void CConnection::set_db_string(std::string db_string)
{
	db_string_ = db_string;
}

void CConnection::set_db_name(std::string db_name)
{
	db_name_ = db_name;
}

string CConnection::get_db_string()
{
	return db_string_;
}

void CConnection::setidletimepoint()
{
	time(&idletimepoint_);
}

void CConnection::output()
{
	CLogger::createinstance()->logdebugmsg("connection=%08x invoke=%d idletime=%d\n", this, invoke_, time(NULL) - idletimepoint_);
}

void*  CConnection::getctctx()
{
	return ctx_;
}

string CConnection::get_db_name()
{
	return db_name_;
}

int CConnection::multi_thread()
{
	#undef SQLCA
	EXEC SQL INCLUDE SQLCA;

	EXEC SQL WHENEVER SQLERROR GOTO sqlerr;

	EXEC SQL ENABLE THREADS;
	
	CLogger::createinstance()->logdebugmsg("start database muti thread mode:success\n");
	return RT_OK;
	
sqlerr:
	CLogger::createinstance()->logdebugmsg("start database muti thread mode:failure\n");
	return RT_NG;
}

int CConnection::start()
{
	#undef SQLCA
	EXEC SQL INCLUDE SQLCA;

	EXEC SQL WHENEVER SQLERROR GOTO sqlerr;

	EXEC SQL BEGIN DECLARE SECTION;
		sql_context ctx = NULL;
	EXEC SQL END DECLARE SECTION;

	EXEC SQL CONTEXT ALLOCATE :ctx;

	this->ctx_ = ctx;

	if (this->ctx_ != NULL)
	{
		CLogger::createinstance()->logdebugmsg("create database context:success\n");
		return RT_OK;
	}
	else
	{
		CLogger::createinstance()->logdebugmsg("create database context:failure\n");
		return RT_NG;
	}

sqlerr:
	return (SqlError(&sqlca, "start()"));
}

int CConnection::stop()
{
	#undef SQLCA
	EXEC SQL INCLUDE SQLCA;

	EXEC SQL WHENEVER SQLERROR GOTO sqlerr;

	EXEC SQL BEGIN DECLARE SECTION;
		sql_context ctx = NULL;
	EXEC SQL END DECLARE SECTION;

	ctx = this->ctx_;
	
	EXEC SQL CONTEXT FREE :ctx;

	CLogger::createinstance()->logdebugmsg("destroy database context:success\n");
	return RT_OK;
	
sqlerr:
	CLogger::createinstance()->logdebugmsg("destroy database context:failure\n");
	return (SqlError(&sqlca, "stop()"));
}

int CConnection::connect()
{
    #undef SQLCA
    EXEC SQL INCLUDE SQLCA;

	EXEC SQL WHENEVER SQLERROR GOTO sqlerr;

	if (this->ctx_ == NULL) return RT_NG;
	if (this->db_connected_ == true) return RT_OK;

	EXEC SQL BEGIN DECLARE SECTION;
		VARCHAR vcConnStr[512]; /*数据库连接串 user/pwd@sid*/
		VARCHAR vcLinkName[64]; /*数据库连接别名*/
		
		sql_context ctx = NULL; /*数据库连接上下文*/
	EXEC SQL END DECLARE SECTION;

	ACE_OS::memset(&vcConnStr, 0x00, sizeof(vcConnStr));
	ACE_OS::memset(&vcLinkName, 0x00, sizeof(vcLinkName));

	ACE_OS::strncpy((char *)vcConnStr.arr, this->db_string_.c_str(), this->db_string_.length());
	vcConnStr.len = ACE_OS::strlen((char *)vcConnStr.arr);

	ACE_OS::strncpy((char *)vcLinkName.arr, this->db_name_.c_str(), this->db_name_.length());
	vcLinkName.len = ACE_OS::strlen((char *)vcLinkName.arr);

	ctx = this->ctx_;
	EXEC SQL CONTEXT USE :ctx;

	EXEC SQL CONNECT :vcConnStr AT :vcLinkName;

	this->db_connected_ = true;

	CLogger::createinstance()->logdebugmsg("connect to database [%s]:success\n", this->db_name_.c_str());
	return RT_OK;

sqlerr:
	this->db_connected_ = false;
	CLogger::createinstance()->logdebugmsg("connect to database [%s]:failure\n", this->db_name_.c_str());
	return (SqlError(&sqlca, "connect()"));
}

int CConnection::disconnect()
{
    #undef SQLCA
    EXEC SQL INCLUDE SQLCA;

	EXEC SQL WHENEVER SQLERROR GOTO sqlerr;

	if (this->ctx_ == NULL) return RT_NG;
	if (this->db_connected_ == false) return RT_OK;

	EXEC SQL BEGIN DECLARE SECTION;
		VARCHAR vcLinkName[64]; /*数据库连接别名*/
		
		sql_context ctx = NULL; /*数据库连接上下文*/
	EXEC SQL END DECLARE SECTION;

	ACE_OS::memset(&vcLinkName, 0x00, sizeof(vcLinkName));

	ACE_OS::strncpy((char *)vcLinkName.arr, this->db_name_.c_str(), this->db_name_.length());
	vcLinkName.len = ACE_OS::strlen((char *)vcLinkName.arr);

	ctx = this->ctx_;
	EXEC SQL CONTEXT USE :ctx;

	/*EXEC SQL AT :vcLinkName ROLLBACK WORK RELEASE;*/
	EXEC SQL AT :vcLinkName COMMIT WORK RELEASE;

	this->db_connected_ = false;


	CLogger::createinstance()->logdebugmsg("disconnect to database [%s]:success\n", this->db_name_.c_str());
	return RT_OK;

sqlerr:
	this->db_connected_ = false;
	CLogger::createinstance()->logdebugmsg("disconnect to database [%s]:failure\n", this->db_name_.c_str());
	return (SqlError(&sqlca, "disconnect()"));
}

int CConnection::reconnect()
{
	this->disconnect();
	
	this->connect();
	
	return this->db_connected_==true ? RT_OK : RT_NG;
}

bool CConnection::is_connected()
{
	return this->db_connected_;
}

int CConnection::SqlError(void *_sqlca, const char *_FunName)
{
	#undef SQLCA
	EXEC SQL INCLUDE SQLCA;

	EXEC SQL WHENEVER SQLERROR GOTO sqlerr;

	if (this->ctx_ == NULL) return RT_NG;
	if (this->db_connected_ == false) return RT_NG;

	int	iRet;

	EXEC SQL BEGIN DECLARE SECTION;
		VARCHAR vcLinkName[64]; /*数据库连接别名*/
		
		sql_context ctx = NULL; /*数据库连接上下文*/

		struct sqlca *sql_ca;
	EXEC SQL END DECLARE SECTION;

	memset(&vcLinkName, 0x00, sizeof(vcLinkName));

	ACE_OS::strncpy((char *)vcLinkName.arr, this->db_name_.c_str(), this->db_name_.length());
	vcLinkName.len = ACE_OS::strlen((char *)vcLinkName.arr);

	ctx = this->ctx_;
	EXEC SQL CONTEXT USE :ctx;

	sql_ca = (struct sqlca *)_sqlca;

	if (sql_ca->sqlcode == 0)
	{
		return	RT_OK;
	}
	if (sql_ca->sqlcode == -1)
	{
		iRet = RT_DOUBLE_KEY;
	}
	else if (((sql_ca->sqlcode == -1012)||(sql_ca->sqlcode == -1041)||(sql_ca->sqlcode == -3114)||(sql_ca->sqlcode == -1003)||(sql_ca->sqlcode == 1455))||((sql_ca->sqlcode <= -12150)&&(sql_ca->sqlcode >= -12285))||((sql_ca->sqlcode >= -12699)&&(sql_ca->sqlcode <= -12500)))
	{
		iRet = RT_CONNECT_FAILED;
		
		this->db_connected_ = false;
	}
	else if (sql_ca->sqlcode == 1403 )  /*no data found*/
	{
		iRet = RT_NO_DATA_FOUND;
	}
	else if (sql_ca->sqlcode == -54)
	{
		iRet = RT_SOURCE_BUSY;
	}
	else if (sql_ca->sqlcode == -1)
	{
		iRet = RT_DOUBLE_KEY;  /*unique constraint violated*/
	}
	else
	{
		iRet = RT_OTHER_ERROR;
	}

	CLogger::createinstance()->logdebugmsg("database [%s] happen error:\nfunction    :[%s]\nresult    :[%d]\nerrorcode:[%d]\nerrorinfo:[%s]\n", 
					this->db_name_.c_str(), 
					_FunName, 
					iRet, 
					sql_ca->sqlcode, 
					sql_ca->sqlerrm.sqlerrmc);
	
	/*ORA-01033: ORACLE initialization or shutdown in progress*/
	/*ORA-24324: service handle not initialized*/
	/*ORA-03114: not connected to ORACLE*/
	/*ORA-01089: immediate shutdown in progress - no operations are permitte */
	/*ORA-24909: call in progress. Current operation cancelled*/
	/*ORA-01012: not logged on*/
	/*ORA-01438: value larger than specified precision allows for this colum*/
	/*ORA-00001: 违反唯一约束条件*/
	/*ORA-01400: 无法将 NULL 插入*/
	
	EXEC SQL AT :vcLinkName ROLLBACK WORK;

sqlerr:
	return iRet;
}

/********************************************************代码演示区**********************************************************/


/*********************************************************************************************
*功        能:SELECT示例
*输        入:NONE
*
*输        出:NONE
*
*返        回:RT_OK:成功,RT_NG:失败
*修 改  记 录:NONE
*********************************************************************************************/
int CConnection::DML_DEMO_1()
{
    #undef SQLCA
    EXEC SQL INCLUDE SQLCA;

	EXEC SQL WHENEVER SQLERROR GOTO sqlerr;

	if (this->ctx_ == NULL) return RT_NG;
	if (this->db_connected_ == false) return RT_NG;

	EXEC SQL BEGIN DECLARE SECTION;
		VARCHAR vcLinkName[64]; /*数据库连接别名*/

		sql_context ctx = NULL; /*数据库连接上下文*/
		
		VARCHAR v_sysdate[32];
	EXEC SQL END DECLARE SECTION;

	ACE_OS::memset(&vcLinkName, 0x00, sizeof(vcLinkName));

	ACE_OS::strncpy((char *)vcLinkName.arr, this->db_name_.c_str(), this->db_name_.length());
	vcLinkName.len = ACE_OS::strlen((char *)vcLinkName.arr);

	ctx = this->ctx_;
	EXEC SQL CONTEXT USE :ctx;

	/*TODO 自有变量赋值*/
	ACE_OS::memset(&v_sysdate, 0x00, sizeof(v_sysdate));

	EXEC SQL AT :vcLinkName 
		SELECT to_char(sysdate, 'YYYY-MM-DD HH24:MI:SS') INTO :v_sysdate
		FROM DUAL;

	CLogger::createinstance()->logdebugmsg("[%s]\n", (char *)v_sysdate.arr);	

	return RT_OK;
/*
notfound:
	CLogger::createinstance()->logdebugmsg("[%s]:DML_DEMO_1() ERROR:No record exist\n", this->db_name_.c_str());
	return RT_NG;
*/
sqlerr:
	return (SqlError(&sqlca, "DML_DEMO_1()"));
}

/*********************************************************************************************
*功        能:INSERT INTO示例
*输        入:NONE
*
*输        出:NONE
*
*返        回:RT_OK:成功,RT_NG:失败
*修 改  记 录:NONE
*********************************************************************************************/
int CConnection::DML_DEMO_2(int i)
{
    #undef SQLCA
    EXEC SQL INCLUDE SQLCA;

	EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
	EXEC SQL WHENEVER NOT FOUND GOTO notfound;

	if (this->ctx_ == NULL) return RT_NG;
	if (this->db_connected_ == false) return RT_NG;

	EXEC SQL BEGIN DECLARE SECTION;
		VARCHAR vcLinkName[64]; /*数据库连接别名*/
		
		sql_context ctx = NULL; /*数据库连接上下文*/

		VARCHAR dyn_stmt[1024];
	EXEC SQL END DECLARE SECTION;

	ACE_OS::memset(&vcLinkName, 0x00, sizeof(vcLinkName));

	ACE_OS::strncpy((char *)vcLinkName.arr, this->db_name_.c_str(), this->db_name_.length());
	vcLinkName.len = ACE_OS::strlen((char *)vcLinkName.arr);

	ctx = this->ctx_;
	EXEC SQL CONTEXT USE :ctx;

	ACE_OS::memset(&dyn_stmt, 0x00, sizeof(dyn_stmt));
		
	/*TODO 自有变量赋值*/	

	dyn_stmt.len = ACE_OS::snprintf((char *)dyn_stmt.arr, sizeof(dyn_stmt.arr), "insert into TB1(COL1, COL2) values(%d, sysdate)", i);

	CLogger::createinstance()->logdebugmsg("SQL:[%s]\n", dyn_stmt.arr);

	EXEC SQL AT :vcLinkName EXECUTE IMMEDIATE :dyn_stmt;

	if (sqlca.sqlcode == 0) 
	{
		CLogger::createinstance()->logdebugmsg("insert into TB1 table success\n");
	}
	else
	{
		CLogger::createinstance()->logdebugmsg("insert into TB1 table failure\n");
	}
	
	EXEC SQL AT :vcLinkName COMMIT WORK;

	return RT_OK;

notfound:

	CLogger::createinstance()->logdebugmsg("[%s]:DML_DEMO_2() ERROR:No record exist\n", this->db_name_.c_str());
	return RT_NG;

sqlerr:
	return (SqlError(&sqlca, "DML_DEMO_2()"));
}

/*********************************************************************************************
*功        能:PREPARE SELECT示例
*输        入:NONE
*
*输        出:NONE
*
*返        回:RT_OK:成功,RT_NG:失败
*修 改  记 录:NONE
*********************************************************************************************/
int CConnection::DML_DEMO_3(int i)
{
    #undef SQLCA
    EXEC SQL INCLUDE SQLCA;

	EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
	/*EXEC SQL WHENEVER NOT FOUND GOTO notfound;*/

	if (this->ctx_ == NULL) return RT_NG;
	if (this->db_connected_ == false) return RT_NG;

	EXEC SQL BEGIN DECLARE SECTION;
		VARCHAR vcLinkName[64]; /*数据库连接别名*/

		sql_context ctx = NULL; /*数据库连接上下文*/

		int     v_col1;
		VARCHAR v_col2[24];
		
		VARCHAR dyn_stmt[1024];
	EXEC SQL END DECLARE SECTION;

	ACE_OS::memset(&vcLinkName, 0x00, sizeof(vcLinkName));

	ACE_OS::strncpy((char *)vcLinkName.arr, this->db_name_.c_str(), this->db_name_.length());
	vcLinkName.len = ACE_OS::strlen((char *)vcLinkName.arr);

	ctx = this->ctx_;
	EXEC SQL CONTEXT USE :ctx;

	/*TODO 自有变量赋值*/
	ACE_OS::memset(&dyn_stmt, 0x00, sizeof(dyn_stmt));

	dyn_stmt.len = ACE_OS::snprintf((char *)dyn_stmt.arr, sizeof(dyn_stmt.arr), "SELECT COL1, to_char(COL2, 'YYYY-MM-DD HH24:MI:SS') FROM TB1 WHERE COL1=%d", i);

	CLogger::createinstance()->logdebugmsg("SQL:[%s]\n", dyn_stmt.arr);

	EXEC SQL AT :vcLinkName DECLARE S STATEMENT;
	
	EXEC SQL AT :vcLinkName PREPARE S FROM :dyn_stmt;
	
	EXEC SQL AT :vcLinkName DECLARE C_TB1_1 CURSOR FOR S;
	
	EXEC SQL AT :vcLinkName OPEN C_TB1_1;
	
		for (;;)
		{
			v_col1 = 0;
			ACE_OS::memset(&v_col2, 0x00, sizeof(v_col2));

			EXEC SQL WHENEVER NOT FOUND DO BREAK;
			EXEC SQL FETCH C_TB1_1 INTO :v_col1, :v_col2;
			if (sqlca.sqlcode != 0) break;

			CLogger::createinstance()->logdebugmsg("(%d):COL2=[%s]\n",
								v_col1, 
								v_col2.arr);
		}
	
	EXEC SQL AT :vcLinkName CLOSE C_TB1_1;
	
	EXEC SQL AT :vcLinkName COMMIT WORK;

	return RT_OK;
/*
notfound:
	CLogger::createinstance()->logdebugmsg("[%s]:DML_DEMO_3() ERROR:No record exist\n", this->db_name_.c_str());
	return RT_NG;
*/
sqlerr:
	return (SqlError(&sqlca, "DML_DEMO_3()"));
}



/*********************************************************************************************
*功        能:EXECUTE PROCEDURE示例
*输        入:存储过程名, 存储过程入参
*
*输        出:存储过程返回值
*
*返        回:RT_OK:成功,RT_NG:失败
*修 改  记 录:NONE
*********************************************************************************************/

int CConnection::DML_DEMO_4(char* inputparam, char* outputparam)
{
	#undef SQLCA
    EXEC SQL INCLUDE SQLCA;

	EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
	EXEC SQL WHENEVER NOT FOUND GOTO notfound;
	
	if (this->ctx_ == NULL) return RT_NG;
	if (this->db_connected_ == false) return RT_NG;

	EXEC SQL BEGIN DECLARE SECTION;
		VARCHAR vcLinkName[64]; /*数据库连接别名*/
		sql_context ctx = NULL; /*数据库连接上下文*/
		VARCHAR  v_input[512];
		VARCHAR  v_output[512];
	EXEC SQL END DECLARE SECTION;

	ACE_OS::memset(&vcLinkName, 0x00, sizeof(vcLinkName));
	ACE_OS::strncpy((char *)vcLinkName.arr, this->db_name_.c_str(), this->db_name_.length());
	vcLinkName.len = ACE_OS::strlen((char *)vcLinkName.arr);
	ctx = this->ctx_;
	EXEC SQL CONTEXT USE :ctx;

	/*TODO 自有变量赋值*/
	v_input.len = ACE_OS::snprintf((char *)v_input.arr, sizeof(v_input.arr),"%s",inputparam);
	ACE_OS::memset(&v_output, 0x00, sizeof(v_output));

	/*执行PL/SQL块*/
	EXEC SQL AT :vcLinkName EXECUTE
	BEGIN
		sp_test(:v_input, :v_output);   
	END;  
	END-EXEC;  

	if (sqlca.sqlcode == 0) 
	{
		ACE_OS::snprintf((char *)outputparam, v_output.len, "%s", v_output.arr);
		outputparam[ v_output.len + 1] = '\0';
		CLogger::createinstance()->logdebugmsg("storage procedure (sp_test) success, result=%s\n", outputparam);
	}
	else
	{
		CLogger::createinstance()->logdebugmsg("storage procedure (sp_test) failure\n");
	}
	
	EXEC SQL AT :vcLinkName COMMIT WORK;

	return RT_OK;
notfound:
	CLogger::createinstance()->logdebugmsg("[%s]:DML_DEMO_4() ERROR:No record exist\n", this->db_name_.c_str());
	return RT_NG;
sqlerr:
	return (SqlError(&sqlca, "DML_DEMO_4()"));
}



/*********************************************************************************************
*功        能:PREPARE PL/SQL块示例
*输        入:NONE
*
*输        出:NONE
*
*返        回:RT_OK:成功,RT_NG:失败
*修 改  记 录:NONE
*********************************************************************************************/
int CConnection::DML_DEMO_5(char* spname, char* inputparam, char* outputparam)
{
    #undef SQLCA
    EXEC SQL INCLUDE SQLCA;

	EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
	EXEC SQL WHENEVER NOT FOUND GOTO notfound;

	if (this->ctx_ == NULL) return RT_NG;
	if (this->db_connected_ == false) return RT_NG;

	EXEC SQL BEGIN DECLARE SECTION;
		VARCHAR vcLinkName[64]; /*数据库连接别名*/

		sql_context ctx = NULL; /*数据库连接上下文*/

		VARCHAR v_input[512];
		VARCHAR v_output[512];
		VARCHAR dyn_stmt[1024];

	EXEC SQL END DECLARE SECTION;

	ACE_OS::memset(&vcLinkName, 0x00, sizeof(vcLinkName));
	ACE_OS::strncpy((char *)vcLinkName.arr, this->db_name_.c_str(), this->db_name_.length());
	vcLinkName.len = ACE_OS::strlen((char *)vcLinkName.arr);

	ctx = this->ctx_;
	EXEC SQL CONTEXT USE :ctx;

	/*TODO 自有变量赋值*/
	ACE_OS::memset(&dyn_stmt, 0x00, sizeof(dyn_stmt));
	dyn_stmt.len = ACE_OS::snprintf((char *)dyn_stmt.arr, sizeof(dyn_stmt.arr), "BEGIN %s(:v_input,:v_output); END;", spname);

	v_input.len =  ACE_OS::snprintf((char *)v_input.arr, sizeof(v_input), "%s", inputparam);
	ACE_OS::memset(&v_output, 0x00, sizeof(v_output));


	//CLogger::createinstance()->logdebugmsg("SQL: [%s]\n", dyn_stmt.arr);


	EXEC SQL AT :vcLinkName DECLARE SS STATEMENT;
	
	EXEC SQL AT :vcLinkName PREPARE SS FROM :dyn_stmt;

	EXEC SQL AT :vcLinkName EXECUTE SS USING :v_input, :v_output;

	if (sqlca.sqlcode == 0) 
	{
		ACE_OS::snprintf((char *)outputparam, v_output.len, "%s", v_output.arr);
		outputparam[ v_output.len + 1] = '\0';
		CLogger::createinstance()->logdebugmsg("storage procedure (%s) success and result=%s\n", spname, outputparam);
	}
	else
	{
		CLogger::createinstance()->logdebugmsg("storage procedure (%s) failure\n", spname);
	}
	
	EXEC SQL AT :vcLinkName COMMIT WORK;

	return RT_OK;

notfound:
	CLogger::createinstance()->logdebugmsg("[%s]:DML_DEMO_5() ERROR:No record exist\n", this->db_name_.c_str());
	return RT_NG;

sqlerr:
	return (SqlError(&sqlca, "DML_DEMO_5()"));
}

cconnectionpool:
#pragma once
#include "Connection.h"
#include "ace/Synch.h"
#include <list>

using namespace std;

typedef list<CConnection*> CONNECTIONLIST;


class CConnectionpool : ACE_Event_Handler
{
public:
	CConnectionpool(string dbstring, string dbname);
	CConnectionpool(string dbstring, string dbname,int maxconn, int minconn, int m_keepalive);
	~CConnectionpool(void);
private:
	CONNECTIONLIST  m_idlelist;
	CONNECTIONLIST  m_busylist;
	string m_dbstring;
	string m_dbname;
	int m_maxconn;
	int m_minconn;
	int m_keepalive;
	ACE_Thread_Mutex m_mutex;
	ACE_Condition<ACE_Thread_Mutex> *m_pcondition;
	bool active_;
private:
	CConnection* applyfor();
	bool payback(CConnection* pconn);
	bool removefromidlelist(CConnection* pconn);
	int addtimer(CConnection *pconn);
	int removetimer(CConnection *pconn);
	virtual int handle_timeout(const ACE_Time_Value &tv, const void *arg);
	int getconnectionsize();
public:
	bool start();
	bool stop();
	int  executesp(char* spname, char* inputparam, char* outparam);
	void output();
	bool getactive();
};

#include "Connectionpool.h"
#include "ace/Reactor.h"
#include "Logger.h"



CConnectionpool::CConnectionpool(string dbstring, string dbname)
{
	m_dbstring = dbstring;
	m_dbname = dbname;
	m_minconn = 2;
	m_maxconn = 4;
	m_keepalive = 10;
	m_pcondition = new ACE_Condition<ACE_Thread_Mutex>(m_mutex);
}

CConnectionpool::CConnectionpool(string dbstring, string dbname, int minconn, int maxconn, int keepalive)
{
	m_dbstring = dbstring;
	m_dbname = dbname;	
	m_minconn = minconn;
	m_maxconn = maxconn;
	m_keepalive = keepalive;
	m_pcondition = new ACE_Condition<ACE_Thread_Mutex>(m_mutex);
}

CConnectionpool::~CConnectionpool(void)
{
	delete m_pcondition;
}

bool CConnectionpool::start()
{
	bool result = false;
	if (CConnection::multi_thread() == RT_OK)
	{
		active_ = true;
		result = true;
	}
	return result;
}

bool CConnectionpool::stop()
{
	active_ = false;
	while(m_busylist.size() != 0)
	{
		ACE_OS::sleep(1);
	}
	printf("all connections are idle, we can destroy them\n");

	typedef CONNECTIONLIST::iterator ITERATOR;
	ITERATOR LI;

	for(LI = m_idlelist.begin(); LI != m_idlelist.end();)
	{
		removetimer(*LI);
		(*LI)->disconnect();
		(*LI)->stop();	
		delete (*LI);
		LI = m_idlelist.erase(LI);
	}

	return true;
}

CConnection* CConnectionpool::applyfor()
{
	m_mutex.acquire();
	CConnection *pconn = NULL;
	if (m_idlelist.size() > 0)
	{	
		pconn = m_idlelist.front();
		m_idlelist.pop_front();
		m_busylist.push_back(pconn);
		//删除定时器
		removetimer(pconn);
	}
	else
	{
		int idle = m_idlelist.size();
		int busy = m_busylist.size();
		int all = idle + busy;

		if (all < m_maxconn)
		{
			pconn = new CConnection(m_dbstring, m_dbname);
			pconn->start();
			pconn->reconnect();
			m_busylist.push_back(pconn);
		}
		else
		{
			while(m_idlelist.size() == 0)
			{
				m_pcondition->signal();
				m_pcondition->wait();
			}
			pconn = m_idlelist.front();
			m_idlelist.pop_front();
			m_busylist.push_back(pconn);
			//删除定时器
			removetimer(pconn);
		}
	}
	m_mutex.release();
	return pconn;
}


bool CConnectionpool::payback(CConnection* pconn)
{
	m_mutex.acquire();
	typedef CONNECTIONLIST::iterator ITERATOR;
	ITERATOR LI;
	bool find = false;
	for(LI = m_busylist.begin(); LI != m_busylist.end();)
	{
		if (*LI == pconn)
		{
			LI = m_busylist.erase(LI);
			find = true;
		}
		else
		{
			LI++;
		}
	}
	if (find)
	{
		m_idlelist.push_back(pconn);
		pconn->setidletimepoint();
		//启动定时器
		addtimer(pconn);
		m_pcondition->signal();
	}
	m_mutex.release();
	return find;
}

int CConnectionpool::getconnectionsize()
{
	m_mutex.acquire();
	int idle = m_idlelist.size();
	int busy = m_busylist.size();
	int all = idle + busy;
	m_mutex.release();
	return all;
}

bool CConnectionpool::removefromidlelist(CConnection* pconn)
{
	m_mutex.acquire();
	typedef CONNECTIONLIST::iterator ITERATOR;
	ITERATOR LI;
	bool find = false;

	CConnection *ptemp = NULL;
	for(LI = m_idlelist.begin(); LI != m_idlelist.end();)
	{
		if (*LI == pconn)
		{
			pconn->disconnect();
			pconn->stop();	
			delete pconn;
			m_idlelist.erase(LI);
			find = true;
			break;
		}
	}
	m_mutex.release();
	return find;
}


int CConnectionpool::executesp(char* spname, char* inputparam, char* outparam)
{
	int ret = -1;
	if (!active_) return ret;
	CConnection *pconn = NULL;
	pconn = applyfor();
	if (pconn != NULL)
	{
		pconn->addinvoke();
		ret = pconn->DML_DEMO_5(spname, inputparam, outparam);
	}
	payback(pconn);
	return ret;
}

void CConnectionpool::output()
{
	m_mutex.acquire();

	typedef CONNECTIONLIST::iterator ITERATOR;
	ITERATOR LI;

	int idle = m_idlelist.size();
	int busy = m_busylist.size();
	int all = idle + busy;

	printf("total=%d\n", all);
	printf("idle=%d\n", idle);
	printf("busy=%d\n", busy);

	printf("........idle list........\n");
	for(LI = m_idlelist.begin(); LI != m_idlelist.end(); LI++)
	{
		(*LI)->output();
	}

	printf("........busy list........\n");
	for(LI = m_busylist.begin(); LI != m_busylist.end(); LI++)
	{
		(*LI)->output();
	}	

	m_mutex.release();
}

int CConnectionpool::addtimer(CConnection *pconn)
{
	ACE_Time_Value tv(this->m_keepalive, 0);
	int timerid = ACE_Reactor::instance()->schedule_timer(this, (void*)pconn, tv);
	pconn->settimerid(timerid);
	return timerid;
}

int CConnectionpool::removetimer(CConnection *pconn)
{
	return ACE_Reactor::instance()->cancel_timer(pconn->gettimerid());
}

int CConnectionpool::handle_timeout(const ACE_Time_Value &tv, const void *arg)
{
	CConnection *pconn = (CConnection*)arg;
	CLogger::createinstance()->logdebugmsg("handle_timeout current=%d connection=%08x timerid=%d ok\n", getconnectionsize(), pconn, pconn->gettimerid());
	if (getconnectionsize() > m_minconn)
	{
		removefromidlelist(pconn);
	}
	return 0;
}

bool CConnectionpool::getactive()
{
	return active_;
}
cclienttask
#pragma once

#include "ace/Task.h"
#include "ace/Synch.h"
#include "Connectionpool.h"

class CClienttask : public ACE_Task<ACE_MT_SYNCH>
{
public:
	CClienttask(void);
	CClienttask(CConnectionpool* connpool, int execount);
	~CClienttask(void);
public:
	virtual int open();
	virtual int svc();
	virtual int close();	
private:
	ACE_thread_t  threads[0x04];
	CConnectionpool* m_pconnpool;
	int m_execount;
};



#include "Clienttask.h"
#include "Logger.h"


CClienttask::CClienttask(void)
{
}

CClienttask::CClienttask(CConnectionpool* connpool, int execount)
{
	m_pconnpool = connpool;
	m_execount = execount;
}

CClienttask::~CClienttask(void)
{
}

int CClienttask::open()
{
	 return activate(THR_NEW_LWP, 4, 0, ACE_DEFAULT_THREAD_PRIORITY, -1, this, 0, 0, 0, threads);
}

int CClienttask::svc()
{
	if (ACE_Thread::self() == threads[0])
	{
		CLogger::createinstance()->logdebugmsg("watch thread started, threadid=%d\n", threads[0]);
		while(true)
		{
			int command = 0;
			scanf_s("%d", &command);
			if(command == 1)
			{
				m_pconnpool->output();
			}
			else if(command == 2)
			{
				m_pconnpool->stop();
			}
		}
	}
	else if (ACE_Thread::self() == threads[1])
	{
		CLogger::createinstance()->logdebugmsg("client task started, threadid=%d\n", threads[1]);
		int i = 0;
		while(i < m_execount && m_pconnpool->getactive())
		{
			char input[100];
			sprintf_s(input, 100, "%05dwangxu%05d", threads[1], i);
			char output[100];
			m_pconnpool->executesp("sp_test", input, output);
			
			i++;
		}
	}
	else if (ACE_Thread::self() == threads[2])
	{
		CLogger::createinstance()->logdebugmsg("client task started, threadid=%d\n", threads[2]);
		int i = 0;
		while(i < m_execount && m_pconnpool->getactive())
		{
			char input[100];
			sprintf_s(input, 100, "%05dwangxu%05d", threads[2], i);
			char output[100];
			m_pconnpool->executesp("sp_test", input, output);
			
			i++;
		}
	}
	else if (ACE_Thread::self() == threads[3])
	{
		CLogger::createinstance()->logdebugmsg("client task started, threadid=%d\n", threads[3]);
		int i = 0;
		while(i < m_execount && m_pconnpool->getactive())
		{
			char input[100];
			sprintf_s(input, 100, "%05dwangxu%05d", threads[3], i);
			char output[100];
			m_pconnpool->executesp("sp_test", input, output);
			
			i++;
		}
	}
	return 0;
}

int CClienttask::close()
{
	return 0;
}
CLogger
#pragma once

#include "ace/Activation_Queue.h"
#include "ace/Method_Request.h"
#include "ace/Task.h"
#include "ace/Future.h"
#include "ace/Auto_Ptr.h"

#include <ctype.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>

using namespace std;

class CLogger : public ACE_Task<ACE_MT_SYNCH>
{
public:
	/*log level*/
	enum LEVEL
	{
		DEBUG = 0x00,
		INFO  = 0x01,
		WARN  = 0x02,
		FAULT = 0x03
	};

	/*output direct*/
	enum DIRECTOR
	{
		SCREENOUT = 0x00,
		FILEOUT   = 0x01,
		BOTH      = 0x02
	};

	/*log mode*/
	enum MODE
	{
		TEST = 0x00,
		RUN  = 0x01
	};

	/*whether the log will be split*/
	enum SPLIT
	{
		ONE  = 0x00,
		FOUR = 0x01
	};

	/*delete log automatic or manual*/
	enum MANAGER
	{
		AUTODEL   = 0x00,
		MANUALDEL = 0x01
	};
public:
	CLogger(void);
	CLogger(LEVEL level, DIRECTOR director, MODE mode, SPLIT split, MANAGER  manager);
	~CLogger(void);

	int logdebugmsg_i(const char* fmt, ...);
	int loginfomsg_i(const char* fmt, ...);
	int logwarnmsg_i(const char* fmt, ...);
	int logfaultmsg_i(const char* fmt, ...);

	ACE_Future<int> logdebugmsg(const char* fmt, ...);
	ACE_Future<int> loginfomsg(const char* fmt, ...);
	ACE_Future<int> logwarnmsg(const char* fmt, ...);
	ACE_Future<int> logfaultmsg(const char* fmt, ...);

	void setparam(LEVEL level, DIRECTOR director, MODE mode, SPLIT split, MANAGER  manager);

	virtual int open();
	virtual int close();
	virtual int svc();
	static CLogger* createinstance();
private:
	static CLogger* _instance;
	ACE_thread_t  threads[0x01];
	ACE_Activation_Queue m_activation_queue;
private:
	LEVEL    m_level;
	DIRECTOR m_director;
	MODE     m_mode;
	SPLIT    m_split;
	MANAGER  m_manager;
	string   m_directory;
	void     createlogdirectory();
	string   getdatetime();
	string   getdate();
	void     closefilehandle();
	FILE*    getonefilehandle();
	FILE*    getdebugfilehandle();
	FILE*    getinfofilehandle();
	FILE*    getwarnfilehandle();
	FILE*    getfaultfilehandle();
	FILE*    m_fpfourdebug;
	string   m_filenamedebug;
	FILE*    m_fpfourinfo;
	string   m_filenameinfo;
	FILE*    m_fpfourwarn;
	string   m_filenamewarn;
	FILE*    m_fpfourfault;
	string   m_filenamefault;
	FILE*    m_fponelog;
	string   m_filenamelog;
public:
	void setlevel(LEVEL level);
	LEVEL getlevel();
	void setdirector(DIRECTOR director);
	DIRECTOR getdirector();
	void setmode(MODE mode);
	MODE getmode();
	void setsplit(SPLIT split);
	SPLIT getsplit();
	void setmanager(MANAGER manager);
	MANAGER getmanager();

};


#include <direct.h>
#include "Logger.h"
#include "Logdebugmsg_MO.h"
#include "Loginfomsg_MO.h"
#include "Logwarnmsg_MO.h"
#include "Logfaultmsg_MO.h"


CLogger* CLogger::_instance = 0;

CLogger* CLogger::createinstance()
{
	if (_instance == 0)
	{
		_instance = new CLogger;
	}
	return _instance;
}


CLogger::CLogger(void)
{
	m_level = CLogger::DEBUG;
	m_director = CLogger::BOTH;
	m_mode = CLogger::TEST;
	m_split = CLogger::FOUR;
	m_manager = CLogger::AUTODEL;
	
	m_fpfourdebug = NULL;
	m_fpfourinfo = NULL;
	m_fpfourwarn = NULL;
	m_fpfourfault = NULL;
	m_fponelog = NULL;

	m_filenamedebug = "null";
	m_filenameinfo = "null";
	m_filenamewarn = "null";
	m_filenamefault = "null";
	m_filenamelog = "null";

	createlogdirectory();

}

CLogger::CLogger(LEVEL level, DIRECTOR director, MODE mode, SPLIT split, MANAGER  manager)
{
	m_level = level;
	m_director = director;
	m_mode = mode;
	m_split = split;
	m_manager = manager;

	m_fpfourdebug = NULL;
	m_fpfourinfo = NULL;
	m_fpfourwarn = NULL;
	m_fpfourfault = NULL;
	m_fponelog = NULL;

	m_filenamedebug = "null";
	m_filenameinfo = "null";
	m_filenamewarn = "null";
	m_filenamefault = "null";
	m_filenamelog = "null";

	createlogdirectory();

}


void CLogger::closefilehandle()
{
	if (m_fpfourdebug != NULL)
	{
		fclose(m_fpfourdebug);
		m_fpfourdebug = NULL;	
		m_filenamedebug = "null";
	}

	if (m_fpfourinfo != NULL)
	{
		fclose(m_fpfourinfo);
		m_fpfourinfo = NULL;	
		m_filenameinfo = "null";
	}

	if (m_fpfourwarn != NULL)
	{
		fclose(m_fpfourwarn);
		m_fpfourwarn = NULL;
		m_filenamewarn = "null";
	}

	if (m_fpfourfault != NULL)
	{
		fclose(m_fpfourfault);
		m_fpfourfault = NULL;
		m_filenamefault = "null";

	}
	
	if (m_fponelog != NULL)
	{
		fclose(m_fponelog);
		m_fponelog = NULL;
		m_filenamelog = "null";
	}
}


CLogger::~CLogger(void)
{
	closefilehandle();
}

void CLogger::setlevel(LEVEL level)
{
	closefilehandle();
	m_level = level;
}

CLogger::LEVEL CLogger::getlevel()
{
	return m_level;
}
	
void CLogger::setdirector(DIRECTOR director)
{
	closefilehandle();
	m_director = director;
}

CLogger::DIRECTOR CLogger::getdirector()
{
	return m_director;
}

void CLogger::setmode(MODE mode)
{
	closefilehandle();
	m_mode = mode;
}

CLogger::MODE CLogger::getmode()
{
	return m_mode;
}

void CLogger::setsplit(SPLIT split)
{
	closefilehandle();
	m_split = split;
}

CLogger::SPLIT CLogger::getsplit()
{
	return m_split;
}

void CLogger::setmanager(MANAGER manager)
{
	m_manager = manager;
}


CLogger::MANAGER CLogger::getmanager()
{
	return m_manager;
}

string CLogger::getdatetime()
{	
	time_t current;
	current = time(NULL);
	struct tm pdatetime;
	int error = localtime_s(&pdatetime, ¤t) ;
	char datetime[100];
	memset(datetime, 0x00, 100);
	sprintf_s(datetime, 100, "%04d-%02d-%02d %02d:%02d %02d",
		pdatetime.tm_year + 1900,
		pdatetime.tm_mon + 1,
		pdatetime.tm_mday,
		pdatetime.tm_hour,
		pdatetime.tm_min,
		pdatetime.tm_sec);

	return string(datetime);
}

string CLogger::getdate()
{
	time_t current;
	struct tm pdatetime;
	time(¤t);
	int error = localtime_s(&pdatetime, ¤t) ;
	char date[100];
	memset(date, 0x00, 100);
	sprintf_s(date, 100, "%04d-%02d-%02d",
		pdatetime.tm_year + 1900,
		pdatetime.tm_mon + 1,
		pdatetime.tm_mday);

	return string(date);
}


int CLogger::logdebugmsg_i(const char* fmt, ...)
{
	if (getlevel() > CLogger::DEBUG) return 0;
	
	va_list ap;
	va_start(ap, fmt);
	if (getdirector() == CLogger::SCREENOUT)
	{
		vfprintf(stdout, fmt, ap);
	}
	else
	{
		if (getsplit() == CLogger::ONE)
		{
			m_fponelog = getonefilehandle();
			vfprintf(m_fponelog, fmt, ap);
			if (getmode() == CLogger::TEST)
			{
				fclose(m_fponelog);
				m_fponelog = NULL;
			}
		}
		else
		{
			m_fpfourdebug = getdebugfilehandle();
			vfprintf(m_fpfourdebug, fmt, ap);
			if (getmode() == CLogger::TEST)
			{
				fclose(m_fpfourdebug);
				m_fpfourdebug = NULL;
			}
		}
		if (getdirector() == CLogger::BOTH)
		{
			vfprintf(stdout, fmt, ap);
		}
	}
	va_end(ap);
	return 0;
}


int CLogger::loginfomsg_i(const char* fmt, ...)
{
	if (getlevel() > CLogger::INFO) return 0;

	va_list ap;
	va_start(ap, fmt);
	if (getdirector() == CLogger::SCREENOUT)
	{
		vfprintf(stdout, fmt, ap);
	}
	else
	{
		if (getsplit() == CLogger::ONE)
		{
			m_fponelog = getonefilehandle();
			vfprintf(m_fponelog, fmt, ap);
			if (getmode() == CLogger::TEST)
			{
				fclose(m_fponelog);
				m_fponelog = NULL;
			}
		}
		else
		{
			m_fpfourinfo = getinfofilehandle();
			vfprintf(m_fpfourinfo, fmt, ap);
			if (getmode() == CLogger::TEST)
			{
				fclose(m_fpfourinfo);
				m_fpfourinfo = NULL;
			}
		}
		if (getdirector() == CLogger::BOTH)
		{
			vfprintf(stdout, fmt, ap);
		}
	}
	va_end(ap);
	return 0;
}


int CLogger::logwarnmsg_i(const char* fmt, ...)
{
	if (getlevel() > CLogger::WARN) return 0;

	va_list ap;
	va_start(ap, fmt);
	if (getdirector() == CLogger::SCREENOUT)
	{
		vfprintf(stdout, fmt, ap);
	}
	else
	{
		if (getsplit() == CLogger::ONE)
		{
			m_fponelog = getonefilehandle();
			vfprintf(m_fponelog, fmt, ap);
			if (getmode() == CLogger::TEST)
			{
				fclose(m_fponelog);
				m_fponelog = NULL;
			}
		}
		else
		{
			m_fpfourwarn = getwarnfilehandle();
			vfprintf(m_fpfourwarn, fmt, ap);
			if (getmode() == CLogger::TEST)
			{
				fclose(m_fpfourwarn);
				m_fpfourwarn = NULL;
			}
		}
		if (getdirector() == CLogger::BOTH)
		{
			vfprintf(stdout, fmt, ap);
		}
	}
	va_end(ap);
	return 0;
}

int CLogger::logfaultmsg_i(const char* fmt, ...)
{
	if (getlevel() > CLogger::FAULT) return 0;
	va_list ap;
	va_start(ap, fmt);
	if (getdirector() == CLogger::SCREENOUT)
	{
		vfprintf(stdout, fmt, ap);
	}
	else
	{
		if (getsplit() == CLogger::ONE)
		{
			m_fponelog = getonefilehandle();
			vfprintf(m_fponelog, fmt, ap);
			if (getmode() == CLogger::TEST)
			{
				fclose(m_fponelog);
				m_fponelog = NULL;
			}
		}
		else
		{
			m_fpfourfault = getfaultfilehandle();
			vfprintf(m_fpfourfault, fmt, ap);
			if (getmode() == CLogger::TEST)
			{
				fclose(m_fpfourfault);
				m_fpfourfault = NULL;
			}
		}
		if (getdirector() == CLogger::BOTH)
		{
			vfprintf(stdout, fmt, ap);
		}
	}
	va_end(ap);
	return 0;
}

void CLogger::createlogdirectory()
{	
	if (m_director == CLogger::SCREENOUT) return;

	string fulldir = "..\\log";	
	
	if (_access(fulldir.c_str(), 0) == -1)
	{
		printf("create %s\n", fulldir.c_str());
		_mkdir(fulldir.c_str());	
	}
	
	fulldir = "..\\log\\debug";
	if (_access(fulldir.c_str(), 0) == -1)
	{
		printf("create %s\n", fulldir.c_str());
		_mkdir(fulldir.c_str());	
	}

	fulldir = "..\\log\\info";
	if (_access(fulldir.c_str(), 0) == -1)
	{
		printf("create %s\n", fulldir.c_str());
		_mkdir(fulldir.c_str());	
	}

	fulldir = "..\\log\\warn";
	if (_access(fulldir.c_str(), 0) == -1)
	{
		printf("create %s\n", fulldir.c_str());
		_mkdir(fulldir.c_str());	
	}

	fulldir = "..\\log\\fault";
	if (_access(fulldir.c_str(), 0) == -1)
	{
		printf("create %s\n", fulldir.c_str());
		_mkdir(fulldir.c_str());	
	}
}



FILE* CLogger::getonefilehandle()
{
	string filename = "..\\log\\" + getdate() + ".log";
	if ((filename.compare(m_filenamelog) == 0) && (m_fponelog != NULL))
	{
	}
	else if((filename.compare(m_filenamelog) == 0) && (m_fponelog == NULL))
	{
		fopen_s(&m_fponelog, filename.c_str(), "a+");
	}
	else if((filename.compare(m_filenamelog) != 0) && (m_fponelog != NULL))
	{
		fclose(m_fponelog);
		m_fponelog = NULL;
		fopen_s(&m_fponelog, filename.c_str(), "a+");
		m_filenamelog = filename;
	}
	else if((filename.compare(m_filenamelog) != 0) && (m_fponelog == NULL))
	{
		fopen_s(&m_fponelog, filename.c_str(), "a+");
		m_filenamelog = filename;
	}
	return m_fponelog;
}

FILE*  CLogger::getdebugfilehandle()
{
	string filename = "..\\log\\debug\\" + getdate() + ".dlog";

	if ((filename.compare(m_filenamedebug) == 0) && (m_fpfourdebug != NULL))
	{
	}
	else if((filename.compare(m_filenamedebug) == 0) && (m_fpfourdebug == NULL))
	{
		fopen_s(&m_fpfourdebug, filename.c_str(), "a+");
	}
	else if((filename.compare(m_filenamedebug) != 0) && (m_fpfourdebug != NULL))
	{
		fclose(m_fpfourdebug);
		m_fpfourdebug = NULL;
		fopen_s(&m_fpfourdebug, filename.c_str(), "a+");
		m_filenamedebug = filename;
	}
	else if((filename.compare(m_filenamedebug) != 0) && (m_fpfourdebug == NULL))
	{
		fopen_s(&m_fpfourdebug, filename.c_str(), "a+");
		m_filenamedebug = filename;
	}
	return m_fpfourdebug;
}

FILE*  CLogger::getinfofilehandle()
{
	string filename = "..\\log\\info\\" + getdate() + ".ilog";

	if ((filename.compare(m_filenameinfo) == 0) && (m_fpfourinfo != NULL))
	{
	}
	else if((filename.compare(m_filenameinfo) == 0) && (m_fpfourinfo == NULL))
	{
		fopen_s(&m_fpfourinfo, filename.c_str(), "a+");
	}
	else if((filename.compare(m_filenameinfo) != 0) && (m_fpfourinfo != NULL))
	{
		fclose(m_fpfourinfo);
		m_fpfourinfo = NULL;
		fopen_s(&m_fpfourinfo, filename.c_str(), "a+");
		m_filenameinfo = filename;
	}
	else if((filename.compare(m_filenameinfo) != 0) && (m_fpfourinfo == NULL))
	{
		fopen_s(&m_fpfourinfo, filename.c_str(), "a+");	
		m_filenameinfo = filename;
	}
	return m_fpfourinfo;
}


FILE*  CLogger::getwarnfilehandle()
{
	string filename = "..\\log\\warn\\" + getdate() + ".wlog";

	if ((filename.compare(m_filenamewarn) == 0) && (m_fpfourwarn != NULL))
	{
	}
	else if((filename.compare(m_filenamewarn) == 0) && (m_fpfourwarn == NULL))
	{
		fopen_s(&m_fpfourwarn, filename.c_str(), "a+");
	}
	else if((filename.compare(m_filenamewarn) != 0) && (m_fpfourwarn != NULL))
	{
		fclose(m_fpfourwarn);
		m_fpfourwarn = NULL;
		fopen_s(&m_fpfourwarn, filename.c_str(), "a+");
		m_filenamewarn = filename;
	}
	else if((filename.compare(m_filenamewarn) != 0) && (m_fpfourwarn == NULL))
	{
		fopen_s(&m_fpfourwarn, filename.c_str(), "a+");	
		m_filenamewarn = filename;
	}
	return m_fpfourwarn;
}


FILE*  CLogger::getfaultfilehandle()
{
	string filename = "..\\log\\fault\\" + getdate() + ".flog";

	if ((filename.compare(m_filenamefault) == 0) && (m_fpfourfault != NULL))
	{
	}
	else if((filename.compare(m_filenamefault) == 0) && (m_fpfourfault == NULL))
	{
		fopen_s(&m_fpfourfault, filename.c_str(), "a+");
	}
	else if((filename.compare(m_filenamefault) != 0) && (m_fpfourfault != NULL))
	{
		fclose(m_fpfourfault);
		m_fpfourfault = NULL;
		fopen_s(&m_fpfourfault, filename.c_str(), "a+");
		m_filenamefault = filename;
	}
	else if((filename.compare(m_filenamefault) != 0) && (m_fpfourfault == NULL))
	{
		fopen_s(&m_fpfourfault, filename.c_str(), "a+");
		m_filenamefault = filename;
	}	
	return m_fpfourfault;
}

int CLogger::open()
{
	return activate(THR_NEW_LWP, 1, 0, ACE_DEFAULT_THREAD_PRIORITY, -1, this, 0, 0, 0, threads);
}

int CLogger::close()
{
	return 0;
}

int CLogger::svc()
{
	while(true)
	{
		auto_ptr<ACE_Method_Request> mo(m_activation_queue.dequeue());
		if (mo->call() == -1)
		break;
	}
	return 0;
}

ACE_Future<int> CLogger::logdebugmsg(const char* fmt, ...)
{	
	char logmsg1[1024];
	memset(logmsg1, 0x00, 1024);
	va_list ap;
	va_start(ap, fmt);
	_vsnprintf_s(logmsg1, 1024, fmt, ap);
	va_end(ap);
	
	char logmsg2[1024];
	memset(logmsg2, 0x00, 1024);
	sprintf_s(logmsg2, 1024, "[%s] %s", getdatetime().c_str(), logmsg1);

	ACE_Future<int> resultant_future;
	CLogdebugmsg_MO *pmo = new CLogdebugmsg_MO(this, logmsg2, resultant_future);
	m_activation_queue.enqueue(pmo);
	return resultant_future;
}


ACE_Future<int> CLogger::loginfomsg(const char* fmt, ...)
{
	char logmsg1[1024];
	memset(logmsg1, 0x00, 1024);
	va_list ap;
	va_start(ap, fmt);
	_vsnprintf_s(logmsg1, 1024, fmt, ap);
	va_end(ap);
	
	char logmsg2[1024];
	memset(logmsg2, 0x00, 1024);
	sprintf_s(logmsg2, 1024, "[%s] %s", getdatetime().c_str(), logmsg1);

	ACE_Future<int> resultant_future;
	m_activation_queue.enqueue(new CLoginfomsg_MO(this, logmsg2, resultant_future));
	return resultant_future;
}

ACE_Future<int> CLogger::logwarnmsg(const char* fmt, ...)
{
	char logmsg1[1024];
	memset(logmsg1, 0x00, 1024);
	va_list ap;
	va_start(ap, fmt);
	_vsnprintf_s(logmsg1, 1024, fmt, ap);
	va_end(ap);
	
	char logmsg2[1024];
	memset(logmsg2, 0x00, 1024);
	sprintf_s(logmsg2, 1024, "[%s] %s", getdatetime().c_str(), logmsg1);

	ACE_Future<int> resultant_future;
	m_activation_queue.enqueue(new CLogwarnmsg_MO(this, logmsg2, resultant_future));
	return resultant_future;
}

ACE_Future<int> CLogger::logfaultmsg(const char* fmt, ...)
{
	char logmsg1[1024];
	memset(logmsg1, 0x00, 1024);
	va_list ap;
	va_start(ap, fmt);
	_vsnprintf_s(logmsg1, 1024, fmt, ap);
	va_end(ap);
	
	char logmsg2[1024];
	memset(logmsg2, 0x00, 1024);
	sprintf_s(logmsg2, 1024, "[%s] %s", getdatetime().c_str(), logmsg1);

	ACE_Future<int> resultant_future;
	m_activation_queue.enqueue(new CLogfaultmsg_MO(this, logmsg2, resultant_future));
	return resultant_future;
}

CLogdebugmsg_MO
#pragma once

#include "ace\method_request.h"
#include "Logger.h"


class CLogdebugmsg_MO : public ACE_Method_Request
{
public:
	CLogdebugmsg_MO(CLogger* logger, const char* fmt, ACE_Future<int> &future_result);
	~CLogdebugmsg_MO(void);
private:
	CLogger * m_plogger;
	char* m_fmt;
	ACE_Future<int> m_future_result;
public:
	int  call();
};



#include "Logdebugmsg_MO.h"


CLogdebugmsg_MO::CLogdebugmsg_MO(CLogger* logger,  const char* fmt, ACE_Future<int> &future_result)
{
	int length = strlen(fmt) + 1;
	m_fmt = new char[length];
	memcpy_s(m_fmt, length, fmt, length);
	m_plogger = logger;
	m_future_result = future_result;
}


CLogdebugmsg_MO::~CLogdebugmsg_MO(void)
{
	delete []m_fmt;
}


int CLogdebugmsg_MO::call()
{
	return m_future_result.set(m_plogger->logdebugmsg_i(m_fmt));
}

CLoginfomsg_MO
#pragma once
#include "ace\method_request.h"
#include "Logger.h"

class CLoginfomsg_MO : public ACE_Method_Request
{
public:
	CLoginfomsg_MO(CLogger* logger, const char* fmt, ACE_Future<int> &future_result);
	~CLoginfomsg_MO(void);
private:
	CLogger * m_plogger;
	char* m_fmt;
	ACE_Future<int> m_future_result;
public:
	int  call();
};

#include "Loginfomsg_MO.h"


CLoginfomsg_MO::CLoginfomsg_MO(CLogger* logger, const char* fmt, ACE_Future<int> &future_result)
{
	int length = strlen(fmt) + 1;
	m_fmt = new char[length];
	memcpy_s(m_fmt, length, fmt, length);
	m_plogger = logger;
	m_future_result = future_result;
}


CLoginfomsg_MO::~CLoginfomsg_MO(void)
{
	delete []m_fmt;
}

int CLoginfomsg_MO::call()
{
	return m_future_result.set(m_plogger->loginfomsg_i(m_fmt));
}

CLogwarnmsg_MO
#pragma once
#include "ace\method_request.h"
#include "Logger.h"

class CLogwarnmsg_MO : public ACE_Method_Request
{
public:
	CLogwarnmsg_MO(CLogger* logger, const char* fmt, ACE_Future<int> &future_result);
	~CLogwarnmsg_MO(void);
private:
	CLogger * m_plogger;
	char* m_fmt;
	ACE_Future<int> m_future_result;
public:
	int  call();
};

#include "Logwarnmsg_MO.h"


CLogwarnmsg_MO::CLogwarnmsg_MO(CLogger* logger, const char* fmt, ACE_Future<int> &future_result)
{
	int length = strlen(fmt) + 1;
	m_fmt = new char[length];
	memcpy_s(m_fmt, length, fmt, length);
	m_plogger = logger;
	m_future_result = future_result;
}


CLogwarnmsg_MO::~CLogwarnmsg_MO(void)
{
	delete []m_fmt;
}

int CLogwarnmsg_MO::call()
{
	return m_future_result.set(m_plogger->logwarnmsg_i(m_fmt));
}

CLogwarnmsg_MO
 
#pragma once
#include "ace\method_request.h"
#include "Logger.h"

class CLogfaultmsg_MO : public ACE_Method_Request
{
public:
	CLogfaultmsg_MO(CLogger* logger, const char* fmt, ACE_Future<int> &future_result);
	~CLogfaultmsg_MO(void);
private:
	CLogger * m_plogger;
	char* m_fmt;
	ACE_Future<int> m_future_result;
public:
	int call();
};


#include "Logfaultmsg_MO.h"


CLogfaultmsg_MO::CLogfaultmsg_MO(CLogger* logger, const char* fmt, ACE_Future<int> &future_result)
{
	int length = strlen(fmt) + 1;
	m_fmt = new char[length];
	memcpy_s(m_fmt, length, fmt, length);
	m_plogger = logger;
	m_future_result = future_result;
}


CLogfaultmsg_MO::~CLogfaultmsg_MO(void)
{
	delete []m_fmt;
}

int CLogfaultmsg_MO::call()
{
	return m_future_result.set(m_plogger->logfaultmsg_i(m_fmt));
}

 

Proc
// Proc.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <ace/OS.h>
#include "Connectionpool.h"
#include "ace/Reactor.h"
#include "Clienttask.h"
#include "Logger.h"



int main(int argc, char* argv[])
{
	ACE_Reactor::instance();
	
	ACE_OS::sleep(2);
	
	CLogger::createinstance()->open();

	CConnectionpool connpool("ucs/ucs@ucs", "ucs", 5, 10, 10);
	connpool.start();

	ACE_OS::sleep(2);

	CClienttask clienttask(&connpool, 1);
	clienttask.open();

	while(1)
	{
		ACE_Reactor::instance()->handle_events();
	}

	return 0;
}

抱歉!评论已关闭.