database_controller.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /*
  2. * @Description: 数据库操作类
  3. * @Author: yct
  4. * @Date: 2020-07-15 14:08:46
  5. * @LastEditTime: 2020-07-19 00:02:06
  6. * @LastEditors: yct
  7. */
  8. #include "database_controller.h"
  9. //初始化
  10. 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)
  11. {
  12. //系统结束标记与连接池大小
  13. mb_exit = false;
  14. m_conn_pool_size = conn_size;
  15. m_db_param.connect_string = std::string("tcp://").append(ip).append(":").append(std::to_string(port));
  16. m_db_param.username = username;
  17. m_db_param.pass = pass;
  18. m_db_param.db_name = db_name;
  19. //mysql驱动
  20. if(m_mysql_driver == nullptr)
  21. {
  22. m_mysql_driver = sql::mysql::get_driver_instance();
  23. }
  24. if(m_mysql_driver == nullptr)
  25. {
  26. mb_initialized = false;
  27. return DB_INIT_FAILED;
  28. }
  29. //创建连接池
  30. m_conn_mutex.lock();
  31. for (int i = 0; i < m_conn_pool_size; i++)
  32. {
  33. try
  34. {
  35. boost::shared_ptr<sql::Connection> t_conn_ptr(m_mysql_driver->connect(m_db_param.connect_string, m_db_param.username, m_db_param.pass));
  36. if (t_conn_ptr->isValid())
  37. {
  38. m_db_conn_pool.push(t_conn_ptr);
  39. std::cout << "conn pushed." << std::endl;
  40. }
  41. else
  42. {
  43. std::cout << "conn create failed." << std::endl;
  44. }
  45. }
  46. catch (sql::SQLException &e)
  47. {
  48. char buf[1024];
  49. memset(buf, 0, 1024);
  50. sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str());
  51. std::cout << buf << std::endl;
  52. }
  53. }
  54. m_conn_mutex.unlock();
  55. //守护线程,检查连接状态并保持连接数量
  56. mp_guard_thread = new std::thread(&Database_controller::database_status_update, this);
  57. mb_initialized = true;
  58. if(check_status() == SUCCESS)
  59. {
  60. mb_connected = true;
  61. }else{
  62. mb_connected = false;
  63. }
  64. return SUCCESS;
  65. }
  66. //反初始化
  67. Error_manager Database_controller::database_controller_uninit()
  68. {
  69. mb_exit = true;
  70. if(mp_guard_thread!=nullptr)
  71. {
  72. if(mp_guard_thread->joinable())
  73. mp_guard_thread->join();
  74. delete mp_guard_thread;
  75. mp_guard_thread = nullptr;
  76. }
  77. }
  78. //数据库连接状态
  79. bool Database_controller::is_connected()
  80. {
  81. return mb_connected;
  82. }
  83. //****** 增删改查功能 *******
  84. //增
  85. Error_manager Database_controller::sql_insert(std::string sql_str)
  86. {
  87. // 1.检查状态,一旦无可用连接,则主动创建一个,若依然失败则直接返回错误
  88. Error_manager ec = check_status();
  89. if(ec != SUCCESS)
  90. {
  91. ec = fill_up_pool(1);
  92. }
  93. if(ec == SUCCESS)
  94. {
  95. // 从连接池获取连接
  96. m_conn_mutex.lock();
  97. boost::shared_ptr<sql::Connection> t_conn_ptr = m_db_conn_pool.front();
  98. m_db_conn_pool.pop();
  99. m_conn_mutex.unlock();
  100. // 使用该连接并在结束判断连接状态,将正常连接丢回队列
  101. if(t_conn_ptr!= nullptr && t_conn_ptr->isValid()){
  102. char buf[1024];
  103. memset(buf, 0, 1024);
  104. try
  105. {
  106. t_conn_ptr->setSchema(m_db_param.db_name);
  107. boost::scoped_ptr<sql::Statement> stmt(t_conn_ptr->createStatement());
  108. stmt->execute(sql_str);
  109. // 丢回队列
  110. if(t_conn_ptr!= nullptr && t_conn_ptr->isValid())
  111. {
  112. m_conn_mutex.lock();
  113. m_db_conn_pool.push(t_conn_ptr);
  114. m_conn_mutex.unlock();
  115. }
  116. return SUCCESS;
  117. }
  118. catch (sql::SQLException &e)
  119. {
  120. /* Use what() (derived from std::runtime_error) to fetch the error message */
  121. sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str());
  122. usleep(1000* 3000);
  123. return Error_manager(DB_INSERT_FAILED, NEGLIGIBLE_ERROR, buf);
  124. }
  125. catch (std::runtime_error &e)
  126. {
  127. sprintf(buf, "# ERR: %s\n ERR: runtime_error in %s ",e.what(),__FILE__);
  128. return Error_manager(DB_INSERT_FAILED, NEGLIGIBLE_ERROR, buf);
  129. }
  130. // catch (std::exception &e)
  131. // {
  132. // sprintf(buf, "# ERR: %s\n ERR: Standard exception in %s ",e.what(),__FILE__);
  133. // return Error_manager(DB_INSERT_FAILED, NEGLIGIBLE_ERROR, buf);
  134. // }
  135. }
  136. else
  137. {
  138. return DB_CONNECT_FAILED;
  139. }
  140. }else{
  141. return ec;
  142. }
  143. }
  144. //删
  145. Error_manager Database_controller::sql_delete(std::string sql_str)
  146. {
  147. // 1.检查状态,一旦无可用连接,则主动创建一个,若依然失败则直接返回错误
  148. Error_manager ec = check_status();
  149. if(ec != SUCCESS)
  150. {
  151. ec = fill_up_pool(1);
  152. }
  153. if(ec == SUCCESS)
  154. {
  155. // 从连接池获取连接
  156. m_conn_mutex.lock();
  157. boost::shared_ptr<sql::Connection> t_conn_ptr = m_db_conn_pool.front();
  158. m_db_conn_pool.pop();
  159. m_conn_mutex.unlock();
  160. // 使用该连接并在结束判断连接状态,将正常连接丢回队列
  161. if(t_conn_ptr!= nullptr && t_conn_ptr->isValid()){
  162. char buf[1024];
  163. memset(buf, 0, 1024);
  164. try
  165. {
  166. t_conn_ptr->setSchema(m_db_param.db_name);
  167. boost::scoped_ptr<sql::Statement> stmt(t_conn_ptr->createStatement());
  168. stmt->execute(sql_str);
  169. // 丢回队列
  170. if(t_conn_ptr!= nullptr && t_conn_ptr->isValid())
  171. {
  172. m_conn_mutex.lock();
  173. m_db_conn_pool.push(t_conn_ptr);
  174. m_conn_mutex.unlock();
  175. }
  176. return SUCCESS;
  177. }
  178. catch (sql::SQLException &e)
  179. {
  180. /* Use what() (derived from std::runtime_error) to fetch the error message */
  181. sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str());
  182. return Error_manager(DB_DELETE_FAILED, NEGLIGIBLE_ERROR, buf);
  183. }
  184. catch (std::runtime_error &e)
  185. {
  186. sprintf(buf, "# ERR: %s\n ERR: runtime_error in %s ",e.what(),__FILE__);
  187. return Error_manager(DB_DELETE_FAILED, NEGLIGIBLE_ERROR, buf);
  188. }
  189. }
  190. else
  191. {
  192. return DB_CONNECT_FAILED;
  193. }
  194. }else{
  195. return ec;
  196. }
  197. }
  198. //改
  199. Error_manager Database_controller::sql_update(std::string sql_str)
  200. {
  201. // 1.检查状态,一旦无可用连接,则主动创建一个,若依然失败则直接返回错误
  202. Error_manager ec = check_status();
  203. if(ec != SUCCESS)
  204. {
  205. ec = fill_up_pool(1);
  206. }
  207. if(ec == SUCCESS)
  208. {
  209. // 从连接池获取连接
  210. m_conn_mutex.lock();
  211. boost::shared_ptr<sql::Connection> t_conn_ptr = m_db_conn_pool.front();
  212. m_db_conn_pool.pop();
  213. m_conn_mutex.unlock();
  214. // 使用该连接并在结束判断连接状态,将正常连接丢回队列
  215. if(t_conn_ptr!= nullptr && t_conn_ptr->isValid()){
  216. char buf[1024];
  217. memset(buf, 0, 1024);
  218. try
  219. {
  220. t_conn_ptr->setSchema(m_db_param.db_name);
  221. boost::scoped_ptr<sql::Statement> stmt(t_conn_ptr->createStatement());
  222. int affected_rows = stmt->executeUpdate(sql_str);
  223. // 丢回队列
  224. if(t_conn_ptr!= nullptr && t_conn_ptr->isValid())
  225. {
  226. m_conn_mutex.lock();
  227. m_db_conn_pool.push(t_conn_ptr);
  228. m_conn_mutex.unlock();
  229. }
  230. if (affected_rows > 0)
  231. {
  232. return SUCCESS;
  233. }
  234. else
  235. {
  236. return DB_UPDATE_FAILED;
  237. }
  238. }
  239. catch (sql::SQLException &e)
  240. {
  241. /* Use what() (derived from std::runtime_error) to fetch the error message */
  242. sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str());
  243. return Error_manager(DB_UPDATE_FAILED, NEGLIGIBLE_ERROR, buf);
  244. }
  245. catch (std::runtime_error &e)
  246. {
  247. sprintf(buf, "# ERR: %s\n ERR: runtime_error in %s ",e.what(),__FILE__);
  248. return Error_manager(DB_UPDATE_FAILED, NEGLIGIBLE_ERROR, buf);
  249. }
  250. }
  251. else
  252. {
  253. return DB_CONNECT_FAILED;
  254. }
  255. }else{
  256. return ec;
  257. }
  258. }
  259. //查
  260. Error_manager Database_controller::sql_query(std::string sql_str, boost::shared_ptr< sql::ResultSet > &query_result)
  261. {
  262. // 1.检查状态,一旦无可用连接,则主动创建一个,若依然失败则直接返回错误
  263. Error_manager ec = check_status();
  264. if(ec != SUCCESS)
  265. {
  266. ec = fill_up_pool(1);
  267. }
  268. if(ec == SUCCESS)
  269. {
  270. // 从连接池获取连接
  271. m_conn_mutex.lock();
  272. boost::shared_ptr<sql::Connection> t_conn_ptr = m_db_conn_pool.front();
  273. // std::cout<<"conn handle: "<<t_conn_ptr<<std::endl;
  274. m_db_conn_pool.pop();
  275. // std::cout<<"conn handle after pop: "<<t_conn_ptr<<std::endl;
  276. m_conn_mutex.unlock();
  277. // 使用该连接并在结束判断连接状态,将正常连接丢回队列
  278. if(t_conn_ptr!= nullptr && t_conn_ptr->isValid()){
  279. char buf[1024];
  280. memset(buf, 0, 1024);
  281. try
  282. {
  283. t_conn_ptr->setSchema(m_db_param.db_name);
  284. boost::scoped_ptr< sql::Statement > stmt(t_conn_ptr->createStatement());
  285. query_result = boost::shared_ptr< sql::ResultSet >(stmt->executeQuery(sql_str));
  286. // 丢回队列
  287. if(t_conn_ptr!= nullptr && t_conn_ptr->isValid())
  288. {
  289. m_conn_mutex.lock();
  290. m_db_conn_pool.push(t_conn_ptr);
  291. m_conn_mutex.unlock();
  292. }
  293. // 检查结果
  294. if(query_result!=nullptr)
  295. {
  296. return SUCCESS;
  297. }else{
  298. return DB_QUERY_FAILED;
  299. }
  300. }
  301. catch (sql::SQLException &e)
  302. {
  303. /* Use what() (derived from std::runtime_error) to fetch the error message */
  304. sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str());
  305. return Error_manager(DB_UPDATE_FAILED, NEGLIGIBLE_ERROR, buf);
  306. }
  307. catch (std::runtime_error &e)
  308. {
  309. sprintf(buf, "# ERR: %s\n ERR: runtime_error in %s ",e.what(),__FILE__);
  310. return Error_manager(DB_UPDATE_FAILED, NEGLIGIBLE_ERROR, buf);
  311. }
  312. }else{
  313. return DB_CONNECT_FAILED;
  314. }
  315. }else{
  316. return ec;
  317. }
  318. }
  319. void Database_controller::database_status_update()
  320. {
  321. while(!mb_exit && mb_initialized)
  322. {
  323. std::cout<<"guard thread working."<<std::endl;
  324. // 检查连接状态,直到获得正常连接或队列为空为止
  325. check_status();
  326. fill_up_pool(m_conn_pool_size);
  327. usleep(1000*DB_UPDATE_INTERVAL_MILLI);
  328. }
  329. }
  330. // 检查连接状态
  331. Error_manager Database_controller::check_status()
  332. {
  333. std::lock_guard<std::mutex> lck(m_conn_mutex);
  334. while (m_db_conn_pool.size() > 0)
  335. {
  336. boost::shared_ptr<sql::Connection> t_conn_ptr = m_db_conn_pool.front();
  337. if (t_conn_ptr != nullptr && t_conn_ptr->isValid())
  338. {
  339. mb_connected = true;
  340. break;
  341. }
  342. else
  343. {
  344. mb_connected = false;
  345. m_db_conn_pool.pop();
  346. }
  347. }
  348. if(mb_connected)
  349. return SUCCESS;
  350. else
  351. return DB_CONNECT_FAILED;
  352. }
  353. // 补充连接
  354. Error_manager Database_controller::fill_up_pool(int add_num)
  355. {
  356. std::lock_guard<std::mutex> lck(m_conn_mutex);
  357. // 填充连接池
  358. int retry_count = 3;
  359. int added_num = 0;
  360. while (m_db_conn_pool.size() < m_conn_pool_size && added_num<add_num)
  361. {
  362. try
  363. {
  364. // 三次创建连接失败则暂时释放锁
  365. if (retry_count <= 0)
  366. {
  367. mb_connected = false;
  368. break;
  369. }
  370. boost::shared_ptr<sql::Connection> t_conn_ptr(m_mysql_driver->connect(m_db_param.connect_string, m_db_param.username, m_db_param.pass));
  371. if (t_conn_ptr != nullptr && t_conn_ptr->isValid())
  372. {
  373. m_db_conn_pool.push(t_conn_ptr);
  374. added_num++;
  375. }
  376. else
  377. {
  378. retry_count--;
  379. }
  380. }
  381. catch (sql::SQLException &e)
  382. {
  383. char buf[1024];
  384. memset(buf, 0, 1024);
  385. sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str());
  386. std::cout << buf << std::endl;
  387. retry_count--;
  388. }
  389. }
  390. m_conn_mutex.unlock();
  391. if(mb_connected)
  392. {
  393. return SUCCESS;
  394. }else{
  395. return DB_CONNECT_FAILED;
  396. }
  397. }