database_controller.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /*
  2. * @Description: 数据库操作类
  3. * @Author: yct
  4. * @Date: 2020-07-15 14:08:46
  5. * @LastEditTime: 2020-07-24 14:19:31
  6. * @LastEditors: yct
  7. */
  8. #include "database_controller.h"
  9. Database_controller::Database_controller()
  10. {
  11. m_database_controller_status = E_UNKNOWN;
  12. mp_reconnect_thread = nullptr;
  13. m_conn_pool_size = 0;
  14. }
  15. Database_controller::~Database_controller()
  16. {
  17. database_controller_uninit();
  18. }
  19. //初始化
  20. Error_manager Database_controller::database_controller_init(std::string ip, int port, std::string username, std::string pass, std::string db_name, int conn_size)
  21. {
  22. Error_manager t_error;
  23. //系统结束标记与连接池大小
  24. // mb_exit = false;
  25. m_conn_pool_size = conn_size;
  26. m_db_param.connect_string = std::string("tcp://").append(ip).append(":").append(std::to_string(port));
  27. m_db_param.username = username;
  28. m_db_param.pass = pass;
  29. m_db_param.db_name = db_name;
  30. if(sql::mysql::get_driver_instance() == nullptr)
  31. {
  32. //胡力 直接修改状态
  33. m_database_controller_status = E_FAULT;
  34. // mb_initialized = false;
  35. return DB_INIT_FAILED;
  36. return Error_manager(Error_code::DB_INIT_FAILED, Error_level::MAJOR_ERROR,
  37. "数据库初始化失败 Database_controller::database_controller_init error ");
  38. }
  39. ////创建补充 数据库连接的通路
  40. t_error = fill_up_connect_channel();
  41. //守护线程,检查连接状态并保持连接数量
  42. m_database_reconnect_condition.reset(false,false,false);
  43. mp_reconnect_thread = new std::thread(&Database_controller::database_reconnect_thread, this);
  44. return t_error;
  45. }
  46. //反初始化
  47. Error_manager Database_controller::database_controller_uninit()
  48. {
  49. // mb_exit = true;
  50. if(mp_reconnect_thread!=nullptr)
  51. {
  52. m_database_reconnect_condition.kill_all();
  53. }
  54. if(mp_reconnect_thread!=nullptr)
  55. {
  56. if(mp_reconnect_thread->joinable())
  57. mp_reconnect_thread->join();
  58. delete mp_reconnect_thread;
  59. mp_reconnect_thread = nullptr;
  60. }
  61. m_database_connect_channel_list.clear();
  62. return SUCCESS;
  63. }
  64. Database_controller::Database_controller_status Database_controller::get_database_controller_status()
  65. {
  66. return m_database_controller_status;
  67. }
  68. Error_manager Database_controller::check_status()
  69. {
  70. if(get_database_controller_status()==E_READY)
  71. {
  72. return SUCCESS;
  73. }
  74. else if(get_database_controller_status() == E_UNKNOWN)
  75. {
  76. return Error_manager(Error_code::DB_INIT_FAILED, Error_level::MINOR_ERROR,
  77. "数据库初始化失败 check_status() error ");
  78. }
  79. else if(get_database_controller_status() == E_DISCONNECT)
  80. {
  81. return Error_manager(Error_code::DB_CONNECT_FAILED, Error_level::MINOR_ERROR,
  82. "数据库连接失败 check_status() error ");
  83. }
  84. else if(get_database_controller_status() == E_FAULT)
  85. {
  86. return Error_manager(Error_code::DB_STATUS_ERROR, Error_level::MINOR_ERROR,
  87. "数据库状态错误 check_status() error ");
  88. }
  89. }
  90. //数据库连接状态
  91. bool Database_controller::is_connected()
  92. {
  93. if ( m_database_controller_status == E_READY)
  94. {
  95. return true;
  96. }
  97. else
  98. {
  99. return false;
  100. }
  101. //
  102. // updata_connect_channel();
  103. // return mb_connected;
  104. }
  105. //****** 增删改查功能 *******
  106. //增
  107. Error_manager Database_controller::sql_insert(std::string sql_str)
  108. {
  109. Error_manager t_error;
  110. //huli
  111. t_error = check_status();
  112. if ( t_error != Error_code::SUCCESS )
  113. {
  114. return t_error;
  115. }
  116. boost::shared_ptr<Database_connect_channel> tp_database_connect_channel;
  117. t_error = occupancy_connect_channel(tp_database_connect_channel);
  118. if ( t_error != Error_code::SUCCESS )
  119. {
  120. return t_error;
  121. }
  122. char buf[1024];
  123. memset(buf, 0, 1024);
  124. try
  125. {
  126. tp_database_connect_channel->mp_connect_channel->setSchema(m_db_param.db_name);
  127. boost::scoped_ptr<sql::Statement> stmt(tp_database_connect_channel->mp_connect_channel->createStatement());
  128. stmt->execute(sql_str);
  129. giveback_connect_channel(tp_database_connect_channel);
  130. return SUCCESS;
  131. }
  132. catch (sql::SQLException &e)
  133. {
  134. giveback_connect_channel(tp_database_connect_channel);
  135. /* Use what() (derived from std::runtime_error) to fetch the error message */
  136. sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s\nsql: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str(), sql_str.c_str());
  137. usleep(1000* 3000);
  138. return Error_manager(DB_INSERT_FAILED, NEGLIGIBLE_ERROR, buf);
  139. }
  140. catch (std::runtime_error &e)
  141. {
  142. giveback_connect_channel(tp_database_connect_channel);
  143. sprintf(buf, "# ERR: %s\n ERR: runtime_error in %s \nsql: %s",e.what(),__FILE__, sql_str.c_str());
  144. return Error_manager(DB_INSERT_FAILED, NEGLIGIBLE_ERROR, buf);
  145. }
  146. // catch (std::exception &e)
  147. // {
  148. // sprintf(buf, "# ERR: %s\n ERR: Standard exception in %s ",e.what(),__FILE__);
  149. // return Error_manager(DB_INSERT_FAILED, NEGLIGIBLE_ERROR, buf);
  150. // }
  151. return SUCCESS;
  152. }
  153. //删
  154. Error_manager Database_controller::sql_delete(std::string sql_str)
  155. {
  156. // 1.检查状态,一旦无可用连接,则主动创建一个,若依然失败则直接返回错误
  157. Error_manager t_error;
  158. //huli
  159. t_error = check_status();
  160. if ( t_error != Error_code::SUCCESS )
  161. {
  162. return t_error;
  163. }
  164. boost::shared_ptr<Database_connect_channel> tp_database_connect_channel;
  165. t_error = occupancy_connect_channel(tp_database_connect_channel);
  166. if ( t_error != Error_code::SUCCESS )
  167. {
  168. return t_error;
  169. }
  170. char buf[1024];
  171. memset(buf, 0, 1024);
  172. try
  173. {
  174. tp_database_connect_channel->mp_connect_channel->setSchema(m_db_param.db_name);
  175. boost::scoped_ptr<sql::Statement> stmt(tp_database_connect_channel->mp_connect_channel->createStatement());
  176. stmt->execute(sql_str);
  177. giveback_connect_channel(tp_database_connect_channel);
  178. return SUCCESS;
  179. }
  180. catch (sql::SQLException &e)
  181. {
  182. /* Use what() (derived from std::runtime_error) to fetch the error message */
  183. giveback_connect_channel(tp_database_connect_channel);
  184. sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s\nsql: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str(), sql_str.c_str());
  185. return Error_manager(DB_DELETE_FAILED, NEGLIGIBLE_ERROR, buf);
  186. }
  187. catch (std::runtime_error &e)
  188. {
  189. giveback_connect_channel(tp_database_connect_channel);
  190. sprintf(buf, "# ERR: %s\n ERR: runtime_error in %s \nsql: %s",e.what(),__FILE__, sql_str.c_str());
  191. return Error_manager(DB_DELETE_FAILED, NEGLIGIBLE_ERROR, buf);
  192. }
  193. return SUCCESS;
  194. }
  195. //改
  196. Error_manager Database_controller::sql_update(std::string sql_str)
  197. {
  198. Error_manager t_error;
  199. //huli
  200. t_error = check_status();
  201. if ( t_error != Error_code::SUCCESS )
  202. {
  203. return t_error;
  204. }
  205. boost::shared_ptr<Database_connect_channel> tp_database_connect_channel;
  206. t_error = occupancy_connect_channel(tp_database_connect_channel);
  207. if ( t_error != Error_code::SUCCESS )
  208. {
  209. return t_error;
  210. }
  211. char buf[1024];
  212. memset(buf, 0, 1024);
  213. try
  214. {
  215. tp_database_connect_channel->mp_connect_channel->setSchema(m_db_param.db_name);
  216. boost::scoped_ptr<sql::Statement> stmt(tp_database_connect_channel->mp_connect_channel->createStatement());
  217. int affected_rows = stmt->executeUpdate(sql_str);
  218. giveback_connect_channel(tp_database_connect_channel);
  219. if (affected_rows > 0)
  220. {
  221. return SUCCESS;
  222. }
  223. else
  224. {
  225. return Error_manager(Error_code::DB_UPDATE_FAILED, Error_level::MINOR_ERROR,
  226. "数据库修改失败 Database_controller::sql_update error ");
  227. }
  228. }
  229. catch (sql::SQLException &e)
  230. {
  231. /* Use what() (derived from std::runtime_error) to fetch the error message */
  232. giveback_connect_channel(tp_database_connect_channel);
  233. sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s\nsql: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str(), sql_str.c_str());
  234. return Error_manager(DB_UPDATE_FAILED, NEGLIGIBLE_ERROR, buf);
  235. }
  236. catch (std::runtime_error &e)
  237. {
  238. giveback_connect_channel(tp_database_connect_channel);
  239. sprintf(buf, "# ERR: %s\n ERR: runtime_error in %s \nsql: %s",e.what(),__FILE__, sql_str.c_str());
  240. return Error_manager(DB_UPDATE_FAILED, NEGLIGIBLE_ERROR, buf);
  241. }
  242. return SUCCESS;
  243. }
  244. //查
  245. Error_manager Database_controller::sql_query(std::string sql_str, boost::shared_ptr< sql::ResultSet > &query_result)
  246. {
  247. Error_manager t_error;
  248. //huli
  249. t_error = check_status();
  250. if ( t_error != Error_code::SUCCESS )
  251. {
  252. return t_error;
  253. }
  254. boost::shared_ptr<Database_connect_channel> tp_database_connect_channel;
  255. t_error = occupancy_connect_channel(tp_database_connect_channel);
  256. if ( t_error != Error_code::SUCCESS )
  257. {
  258. return t_error;
  259. }
  260. char buf[1024];
  261. memset(buf, 0, 1024);
  262. try
  263. {
  264. tp_database_connect_channel->mp_connect_channel->setSchema(m_db_param.db_name);
  265. boost::scoped_ptr<sql::Statement> stmt(tp_database_connect_channel->mp_connect_channel->createStatement());
  266. query_result = boost::shared_ptr< sql::ResultSet >(stmt->executeQuery(sql_str));
  267. giveback_connect_channel(tp_database_connect_channel);
  268. // 检查结果
  269. if(query_result==nullptr)
  270. {
  271. return Error_manager(Error_code::DB_QUERY_FAILED, Error_level::MAJOR_ERROR,
  272. "数据库查询失败 Database_controller::sql_query error ");
  273. }
  274. }
  275. catch (sql::SQLException &e)
  276. {
  277. /* Use what() (derived from std::runtime_error) to fetch the error message */
  278. giveback_connect_channel(tp_database_connect_channel);
  279. sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s\nsql: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str(), sql_str.c_str());
  280. return Error_manager(DB_UPDATE_FAILED, NEGLIGIBLE_ERROR, buf);
  281. }
  282. catch (std::runtime_error &e)
  283. {
  284. giveback_connect_channel(tp_database_connect_channel);
  285. sprintf(buf, "# ERR: %s\n ERR: runtime_error in %s \nsql: %s",e.what(),__FILE__, sql_str.c_str());
  286. return Error_manager(DB_UPDATE_FAILED, NEGLIGIBLE_ERROR, buf);
  287. }
  288. return SUCCESS;
  289. }
  290. void Database_controller::database_reconnect_thread()
  291. {
  292. //hili 这个用条件变量去控制
  293. while (m_database_reconnect_condition.is_alive())
  294. {
  295. m_database_reconnect_condition.wait_for_ex(std::chrono::seconds(1));
  296. if (m_database_reconnect_condition.is_alive())
  297. {
  298. updata_connect_channel();
  299. fill_up_connect_channel();
  300. }
  301. }
  302. }
  303. // 检查连接状态
  304. Error_manager Database_controller::updata_connect_channel()
  305. {
  306. for (auto iter = m_database_connect_channel_list.begin(); iter != m_database_connect_channel_list.end();)
  307. {
  308. if ((*iter)->mp_connect_channel == nullptr)
  309. {
  310. iter = m_database_connect_channel_list.erase(iter);
  311. }
  312. else if ( (*iter)->m_occupancy_lock.try_lock() )
  313. {
  314. if( (*iter)->mp_connect_channel->isValid() )
  315. {
  316. (*iter)->m_occupancy_lock.unlock();
  317. ++iter;
  318. }
  319. else
  320. {
  321. (*iter)->m_occupancy_lock.unlock();
  322. iter = m_database_connect_channel_list.erase(iter);
  323. }
  324. }
  325. else
  326. {
  327. ++iter;
  328. }
  329. }
  330. return Error_code::SUCCESS;
  331. }
  332. ////创建补充 数据库连接的通路
  333. Error_manager Database_controller::fill_up_connect_channel()
  334. {
  335. if ( m_conn_pool_size <=0 )
  336. {
  337. return Error_manager(Error_code::DB_CONNECT_CHANNEL_NUMBER_ERROR, Error_level::MINOR_ERROR,
  338. "数据库连接通道数量错误 Database_controller::fill_up_connect_channel() error ");
  339. }
  340. // 填充连接池
  341. int retry_count = DB_RECONNECTION_NUMBER;
  342. //胡力 建议修改如下
  343. while (m_database_connect_channel_list.size() < m_conn_pool_size && retry_count > 0)
  344. {
  345. try
  346. {
  347. //胡力 数据库连接的指针 建议改名 tp_sql_connnect
  348. boost::shared_ptr<sql::Connection> tp_connect_channel(sql::mysql::get_driver_instance()->connect(m_db_param.connect_string, m_db_param.username, m_db_param.pass));
  349. if (tp_connect_channel != nullptr && tp_connect_channel->isValid())
  350. {
  351. boost::shared_ptr<Database_connect_channel> tp_database_connect_channel(new Database_connect_channel);
  352. tp_database_connect_channel->mp_connect_channel = tp_connect_channel;
  353. // tp_database_connect_channel->m_occupancy_lock.unlock();
  354. m_database_connect_channel_list.push_back(tp_database_connect_channel);
  355. }
  356. else
  357. {
  358. retry_count--;
  359. }
  360. }
  361. catch (sql::SQLException &e)
  362. {
  363. char buf[1024];
  364. memset(buf, 0, 1024);
  365. sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str());
  366. retry_count--;
  367. }
  368. }
  369. if ( retry_count <= 0 )
  370. {
  371. m_database_controller_status = E_DISCONNECT;
  372. //胡力 如果报错 队列中部分成功要回收处理 需要讨论!!!!!!!!!!!!!!!!!!
  373. m_database_connect_channel_list.clear();
  374. return Error_manager(Error_code::DB_CONNECT_FAILED, Error_level::MINOR_ERROR,
  375. "数据库连接失败 Database_controller::fill_up_connect_channel() error ");
  376. }
  377. else
  378. {
  379. m_database_controller_status = E_READY;
  380. return Error_code::SUCCESS;
  381. }
  382. return SUCCESS;
  383. }
  384. //zhan you jieyong
  385. Error_manager Database_controller::occupancy_connect_channel(boost::shared_ptr<Database_connect_channel> & p_database_connect_channel)
  386. {
  387. for (auto iter = m_database_connect_channel_list.begin(); iter != m_database_connect_channel_list.end(); ++iter)
  388. {
  389. if ( (*iter)->mp_connect_channel != nullptr)
  390. {
  391. if ( (*iter)->m_occupancy_lock.try_lock() )
  392. {
  393. if ( (*iter)->mp_connect_channel->isValid() )
  394. // if ( !(*iter)->mp_connect_channel->isClosed() )
  395. {
  396. p_database_connect_channel = (*iter);
  397. return Error_code::SUCCESS;
  398. }
  399. (*iter)->m_occupancy_lock.unlock();
  400. }
  401. }
  402. //
  403. //
  404. //
  405. // if ( (*iter)->mp_connect_channel != nullptr && (*iter)->mp_connect_channel->isValid() )
  406. // {
  407. // if ( (*iter)->m_occupancy_lock.try_lock() )
  408. // {
  409. // p_database_connect_channel = (*iter);
  410. // return Error_code::SUCCESS;
  411. // }
  412. //
  413. // }
  414. }
  415. //if not find
  416. return Error_manager(Error_code::DB_CONNECT_CHANNEL_NOT_FOUND, Error_level::MINOR_ERROR,
  417. "数据库连接通道未找到 Database_controller::occupancy_connect_channel error ");
  418. }
  419. //guihuan
  420. Error_manager Database_controller::giveback_connect_channel(boost::shared_ptr<Database_connect_channel> p_database_connect_channel)
  421. {
  422. if ( p_database_connect_channel == nullptr )
  423. {
  424. return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR,
  425. "指针为空 Database_controller::giveback_connect_channel error ");
  426. }
  427. p_database_connect_channel->m_occupancy_lock.unlock();
  428. return Error_code::SUCCESS;
  429. }