database_controller.cpp 13 KB

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