my_con.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*
  2. * Copyright (C) 2001-2004 iptel.org
  3. * Copyright (C) 2006-2007 iptelorg GmbH
  4. *
  5. * This file is part of Kamailio, a free SIP server.
  6. *
  7. * Kamailio is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version
  11. *
  12. * Kamailio is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include "my_con.h"
  22. #include "mysql_mod.h"
  23. #include "my_uri.h"
  24. #include "../../mem/mem.h"
  25. #include "../../dprint.h"
  26. #include "../../ut.h"
  27. #include <string.h>
  28. #include <time.h>
  29. /*
  30. * Close the connection and release memory
  31. */
  32. static void my_con_free(db_con_t* con, struct my_con* payload)
  33. {
  34. if (!payload) return;
  35. /* Delete the structure only if there are no more references
  36. * to it in the connection pool
  37. */
  38. if (db_pool_remove((db_pool_entry_t*)payload) == 0) return;
  39. db_pool_entry_free(&payload->gen);
  40. if (payload->con) pkg_free(payload->con);
  41. pkg_free(payload);
  42. }
  43. int my_con_connect(db_con_t* con)
  44. {
  45. struct my_con* mcon;
  46. struct my_uri* muri;
  47. mcon = DB_GET_PAYLOAD(con);
  48. muri = DB_GET_PAYLOAD(con->uri);
  49. /* Do not reconnect already connected connections */
  50. if (mcon->flags & MY_CONNECTED) return 0;
  51. DBG("mysql: Connecting to %.*s:%.*s\n",
  52. con->uri->scheme.len, ZSW(con->uri->scheme.s),
  53. con->uri->body.len, ZSW(con->uri->body.s));
  54. if (my_connect_to) {
  55. if (mysql_options(mcon->con, MYSQL_OPT_CONNECT_TIMEOUT,
  56. (char*)&my_connect_to))
  57. WARN("mysql: failed to set MYSQL_OPT_CONNECT_TIMEOUT\n");
  58. }
  59. #if MYSQL_VERSION_ID >= 40101
  60. if ((my_client_ver >= 50025) ||
  61. ((my_client_ver >= 40122) &&
  62. (my_client_ver < 50000))) {
  63. if (my_send_to) {
  64. if (mysql_options(mcon->con, MYSQL_OPT_WRITE_TIMEOUT ,
  65. (char*)&my_send_to))
  66. WARN("mysql: failed to set MYSQL_OPT_WRITE_TIMEOUT\n");
  67. }
  68. if (my_recv_to){
  69. if (mysql_options(mcon->con, MYSQL_OPT_READ_TIMEOUT ,
  70. (char*)&my_recv_to))
  71. WARN("mysql: failed to set MYSQL_OPT_READ_TIMEOUT\n");
  72. }
  73. }
  74. #endif
  75. if (!mysql_real_connect(mcon->con, muri->host, muri->username,
  76. muri->password, muri->database, muri->port, 0, 0)) {
  77. LOG(L_ERR, "mysql: %s\n", mysql_error(mcon->con));
  78. return -1;
  79. }
  80. DBG("mysql: Connection type is %s\n", mysql_get_host_info(mcon->con));
  81. DBG("mysql: Protocol version is %d\n", mysql_get_proto_info(mcon->con));
  82. DBG("mysql: Server version is %s\n", mysql_get_server_info(mcon->con));
  83. mcon->flags |= MY_CONNECTED;
  84. return 0;
  85. }
  86. void my_con_disconnect(db_con_t* con)
  87. {
  88. struct my_con* mcon;
  89. mcon = DB_GET_PAYLOAD(con);
  90. if ((mcon->flags & MY_CONNECTED) == 0) return;
  91. DBG("mysql: Disconnecting from %.*s:%.*s\n",
  92. con->uri->scheme.len, ZSW(con->uri->scheme.s),
  93. con->uri->body.len, ZSW(con->uri->body.s));
  94. mysql_close(mcon->con);
  95. mcon->flags &= ~MY_CONNECTED;
  96. /* Increase the variable that keeps track of number of connection
  97. * resets on this connection. The mysql module uses the variable to
  98. * determine when a pre-compiled command needs to be uploaded to the
  99. * server again. If the number in the my_con structure is larger than
  100. * the number kept in my_cmd then it means that we have to upload the
  101. * command to the server again because the connection was reset.
  102. */
  103. mcon->resets++;
  104. }
  105. int my_con(db_con_t* con)
  106. {
  107. struct my_con* ptr;
  108. /* First try to lookup the connection in the connection pool and
  109. * re-use it if a match is found
  110. */
  111. ptr = (struct my_con*)db_pool_get(con->uri);
  112. if (ptr) {
  113. DBG("mysql: Connection to %.*s:%.*s found in connection pool\n",
  114. con->uri->scheme.len, ZSW(con->uri->scheme.s),
  115. con->uri->body.len, ZSW(con->uri->body.s));
  116. goto found;
  117. }
  118. ptr = (struct my_con*)pkg_malloc(sizeof(struct my_con));
  119. if (!ptr) {
  120. LOG(L_ERR, "mysql: No memory left\n");
  121. goto error;
  122. }
  123. memset(ptr, '\0', sizeof(struct my_con));
  124. if (db_pool_entry_init(&ptr->gen, my_con_free, con->uri) < 0) goto error;
  125. ptr->con = (MYSQL*)pkg_malloc(sizeof(MYSQL));
  126. if (!ptr->con) {
  127. LOG(L_ERR, "mysql: No enough memory\n");
  128. goto error;
  129. }
  130. mysql_init(ptr->con);
  131. DBG("mysql: Creating new connection to: %.*s:%.*s\n",
  132. con->uri->scheme.len, ZSW(con->uri->scheme.s),
  133. con->uri->body.len, ZSW(con->uri->body.s));
  134. /* Put the newly created mysql connection into the pool */
  135. db_pool_put((struct db_pool_entry*)ptr);
  136. DBG("mysql: Connection stored in connection pool\n");
  137. found:
  138. /* Attach driver payload to the db_con structure and set connect and
  139. * disconnect functions
  140. */
  141. DB_SET_PAYLOAD(con, ptr);
  142. con->connect = my_con_connect;
  143. con->disconnect = my_con_disconnect;
  144. return 0;
  145. error:
  146. if (ptr) {
  147. db_pool_entry_free(&ptr->gen);
  148. if (ptr->con) pkg_free(ptr->con);
  149. pkg_free(ptr);
  150. }
  151. return 0;
  152. }