/*
 * @Description: 数据库操作类
 * @Author: yct
 * @Date: 2020-07-14 14:09:35
 * @LastEditTime: 2020-07-18 23:57:10
 * @LastEditors: yct
 */ 
#ifndef DATABASE_CONTROLLER_HH
#define DATABASE_CONTROLLER_HH

#include <mysql_driver.h>
#include <mysql_connection.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>

#include "../tool/singleton.h"
#include "../tool/thread_condition.h"
#include "../error_code/error_code.h"
#include "./database_communication_configuration.pb.h"
#include <stdio.h>
#include <mutex>
#include <queue>
#include <thread>
#include <atomic>
#include <unistd.h>
#include <string.h>
#include <iostream>
#include <cstddef>
#include <boost/shared_ptr.hpp>
#include <proto_tool.h>
#include <glog/logging.h>



#define DB_UPDATE_INTERVAL_MILLI 20000

//胡力  数据库连接线路的默认个数		默认5个
#define DB_CONNECT_QUEUE_SIZE 		5

//胡力  数据库尝试重新连接的次数    默认3次
#define DB_RECONNECTION_NUMBER 		3


#define DATABASE_COMMUNICATION_PARAMETER_PATH "../setting/database_communication.prototxt"
class Database_controller : public Singleton<Database_controller>
{
    // 子类必须把父类设定为友元函数，这样父类才能使用子类的私有构造函数。
    friend class Singleton<Database_controller>;
public:
    typedef struct DB_PARAM
    {
        std::string connect_string;
        std::string username;
        std::string pass;
        std::string db_name;
    } db_param;

	//huli 新增数据库的状态
	enum Database_controller_status
	{
	    E_UNKNOWN               = 0,    //默认未知
	    E_READY               	= 1,    //正常待机
		E_DISCONNECT			= 2,	//断连
	    E_FAULT					= 3,	//故障
	};

	struct Database_connect_channel
	{
		boost::shared_ptr< sql::Connection> 		mp_connect_channel;
		std::mutex									m_occupancy_lock;
	};


private:
	// 父类的构造函数必须保护，子类的构造函数必须私有。
	Database_controller() ;
public:
    // 必须关闭拷贝构造和赋值构造，只能通过 get_instance 函数来进行操作唯一的实例。
    Database_controller(const Database_controller &) = delete;
    Database_controller &operator=(const Database_controller &) = delete;
    ~Database_controller();

    //初始化
	Error_manager database_controller_init();
	//从文本导入
	Error_manager database_controller_init_from_protobuf(std::string prototxt_path);
    Error_manager database_controller_init(std::string ip, int port, std::string username, std::string pass, std::string db_name, int conn_size=DB_CONNECT_QUEUE_SIZE);
    //反初始化
    Error_manager database_controller_uninit();


	Database_controller_status get_database_controller_status();
	Error_manager check_status();

    //数据库连接状态
    bool is_connected();
    //****** 增删改查功能 *******
    //增
    Error_manager sql_insert(std::string sql_str);
    //删
    Error_manager sql_delete(std::string sql_str);
    //改
    Error_manager sql_update(std::string sql_str);
    //查
    Error_manager sql_query(std::string sql_str, boost::shared_ptr< sql::ResultSet > &query_result);


    //控制语句 LOCK  UNLOCK COMMIT 等
	Error_manager sql_control(std::string sql_str);

private:
    // 守护线程，维持连接数量，以及自身状态更新
    void database_reconnect_thread();
    // 检查gengxin连接
    Error_manager updata_connect_channel();
    //创建补充 数据库连接的通路
    Error_manager fill_up_connect_channel();

	//zhan you   jieyong
	Error_manager occupancy_connect_channel(boost::shared_ptr<Database_connect_channel> & p_database_connect_channel);

	//guihuan
	Error_manager giveback_connect_channel(boost::shared_ptr<Database_connect_channel> p_database_connect_channel);

private:

	//huli 新增数据库的状态
	Database_controller_status			m_database_controller_status;

    //数据库连接通路的集合
	std::list< boost::shared_ptr<Database_connect_channel> > m_database_connect_channel_list;

	//维持连接数量，以及自身状态更新条件变量
	Thread_condition m_database_reconnect_condition;
	//重连线程
    std::thread *mp_reconnect_thread;


    //连接池大小
    int m_conn_pool_size;
    //连接参数
    db_param m_db_param; 

};

#endif // !DATABASE_CONTROLLER_HH
