database_controller.cpp 13 KB

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