#ifndef YASERVER_MYSQLCONNPOOL_H_
#define YASERVER_MYSQLCONNPOOL_H_

#include <mysql.h>
#include <list>

#ifndef MAXCRITICALSECTIONSPINCOUNT
#define MAXCRITICALSECTIONSPINCOUNT 4000
#endif // !MAXCRITICALSECTIONSPINCOUNT

using namespace std;

class CMysqlConn{
public:
	CMysqlConn(const char *option, const char *host, const char *user,
		const char *password, const char* dbname, unsigned int port, 
		const char *unix_socket, unsigned long clientflag, bool &state);
	virtual ~CMysqlConn();
public:
	// 连接到数据库
	int SetOption();
	int Open();
	// 关闭数据库clei
	int Close();
	// 数据库是否已连接
	bool IsOpen() const;
	// query

	MYSQL_RES * Execute(const char * strSQL, int &err);
	void MultiExecute( const char * strSQL, int &err);

private:
	MYSQL * m_pConn;
	bool m_bValid; // 已被初始化成功标识
	bool m_bOpen;

	const char * m_option;
	const char * m_host;
	const char * m_user;
	const char * m_pwd;
	const char * m_db;
	unsigned int m_port;
	const char * m_unix_socket;
	unsigned long m_clientflag;
};

typedef std::list<CMysqlConn*> DBConnectList;

class CMysqlConnPool
{
public:
	// 获取实例指针
	static CMysqlConnPool &Instanse(){
		static CMysqlConnPool m_pInstanse;
		return m_pInstanse;
	};

	// 初始化所有连接
	int InitAllConn();

	// 关闭所有连接
	void CloseAllConn();
	// 获取一个空闲连接
	CMysqlConn* GetNewConn();
	// 交还连接给空闲队列
	int RestoreConn(CMysqlConn* pDBEngine);
	void Init(const char* szOption, const char *szHost, const char *szUser, const char *szPwd, const char *szDbName,
		unsigned int nPort, const char * szUnixSocket, unsigned long nClientFlag);
private:
	// 唯一实例
	CMysqlConnPool();
	virtual ~CMysqlConnPool();
	// 创建一个连接
	int InitNewConn();
	// 关闭一个连接
	void CloseConn(CMysqlConn* pDBEngine);
	// 停止工作线程
	void StopThread();

	// 判断是否需要停止
	BOOL IsNeedStop();
	BOOL IsNeedConnection();
	// 将守卫类作为连接池类的友元类
	friend class CDBConnGuard;

	// 空闲数据库连接队列
	DBConnectList m_listIdleConnection;
	// 在使用的数据库连接
	DBConnectList m_listBusyConnection;

	// 队列保护的临界区
	CRITICAL_SECTION m_csIdleConnList;
	CRITICAL_SECTION m_csBusyConnList;

	// 可用连接总数的三个指标：最大、最小
	unsigned int m_nMaxCount;
	unsigned int m_nMinCount;

	// 数据库信息
	std::string m_strHost;
	std::string m_strUser;
	std::string m_strPwd;
	std::string m_strUnixSocket;
	std::string m_strOption;
	std::string m_strDbName;
	//const char * m_strHost;
	//const char * m_strUser;
	//const char * m_strPwd;
	//const char * m_strUnixSocket;
	//const char * m_strOption;
	//const char * m_strDbName;
	unsigned int m_nPort;
	unsigned long m_nClientFlag;

	// 维护线程
	HANDLE m_hMaintanceThread; // 线程句柄
	HANDLE m_hHaveData; // 信号

	BOOL m_bNeedStop; // 管理线程起停的标志位
	BOOL m_bNeedConnection; // 需要创建连接的标志
	static DWORD WINAPI thread_run( LPVOID pdata);
};

class CDBConnGuard{
public:
	CDBConnGuard(CMysqlConn* &pDbConn){
		pDbConn = CMysqlConnPool::Instanse().GetNewConn();
		//判断连接的有效性
		m_pDbConn = pDbConn;
	}
	virtual ~CDBConnGuard()
	{
		CMysqlConnPool::Instanse().RestoreConn(m_pDbConn);
	}
private:
	CMysqlConn * m_pDbConn;
};

#define GetConnPool() CMysqlConnPool::Instanse()

#endif //YASERVER_MYSQLCONNPOOL_H_