ul_db.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. /* sp-ul_db module
  2. *
  3. * Copyright (C) 2007 1&1 Internet AG
  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 "../../lib/srdb1/db.h"
  22. #include "ul_db.h"
  23. #include "p_usrloc_mod.h"
  24. #include "ul_db_failover.h"
  25. #include "ul_db_ins.h"
  26. #include "ul_db_repl.h"
  27. #include "ul_db_ins_upd.h"
  28. #include "ul_db_upd.h"
  29. #include "ul_db_del.h"
  30. #include "ul_db_query.h"
  31. #include "ul_check.h"
  32. #include <unistd.h>
  33. ul_db_handle_t dbh_tmp;
  34. ul_master_db_set_t mdb;
  35. int required_caps = DB_CAP_QUERY | DB_CAP_RAW_QUERY | DB_CAP_INSERT | DB_CAP_DELETE | DB_CAP_UPDATE | DB_CAP_INSERT_UPDATE;
  36. static char query[UL_DB_QUERY_LEN];
  37. typedef struct db_dbf_dbres {
  38. db1_res_t * res;
  39. db_func_t * dbf;
  40. } db_dbf_dbres_t;
  41. #define UL_DB_RES_LIMIT 20
  42. db_dbf_dbres_t results[UL_DB_RES_LIMIT];
  43. static int add_dbf(db1_res_t * res, db_func_t * dbf);
  44. static db_func_t * get_and_remove_dbf(db1_res_t * res);
  45. int ul_db_init(void) {
  46. mdb.read.url = &read_db_url;
  47. mdb.write.url = &write_db_url;
  48. memset(results, 0, sizeof(results));
  49. if(db_master_write){
  50. if(db_bind_mod(mdb.write.url, &mdb.write.dbf) < 0) {
  51. LM_ERR("could not bind api for write db.\n");
  52. return -1;
  53. }
  54. if(!(mdb.write.dbf.cap & required_caps)) {
  55. LM_ERR("db api of write db doesn't support required operation.\n");
  56. return -1;
  57. }
  58. LM_INFO("write db initialized");
  59. }
  60. if(db_bind_mod(mdb.read.url, &mdb.read.dbf) < 0) {
  61. LM_ERR("could not bind db api for read db.\n");
  62. return -1;
  63. }
  64. if(!(mdb.read.dbf.cap & required_caps)) {
  65. LM_ERR("db api of read db doesn't support required operation.\n");
  66. return -1;
  67. }
  68. LM_INFO("read db initialized");
  69. return 0;
  70. }
  71. int ul_db_child_init(void) {
  72. if(mdb.read.dbh){
  73. mdb.read.dbf.close(mdb.read.dbh);
  74. mdb.read.dbh = NULL;
  75. }
  76. if(mdb.write.dbh){
  77. mdb.write.dbf.close(mdb.write.dbh);
  78. mdb.write.dbh = NULL;
  79. }
  80. if((mdb.read.dbh = mdb.read.dbf.init(mdb.read.url)) == NULL) {
  81. LM_ERR("could not connect to sip master db (read).\n");
  82. return -1;
  83. }
  84. LM_INFO("read db connection for children initialized");
  85. if(ul_db_child_locnr_init() == -1) return -1;
  86. LM_INFO("location number is %d\n", max_loc_nr);
  87. if(db_master_write){
  88. if((mdb.write.dbh = mdb.write.dbf.init(mdb.write.url)) == NULL) {
  89. LM_ERR("could not connect to sip master db (write).\n");
  90. return -1;
  91. }
  92. LM_INFO("write db connection for children initialized");
  93. }
  94. return 0;
  95. }
  96. int ul_db_child_locnr_init(void) {
  97. if(!mdb.read.dbh){
  98. LM_ERR("Sip master DB connection(read) is down");
  99. return -1;
  100. }
  101. if(load_location_number(&mdb.read.dbf, mdb.read.dbh, &max_loc_nr) != 0){
  102. LM_ERR("could not load location number\n");
  103. return -1;
  104. }
  105. return 0;
  106. }
  107. void ul_db_shutdown(void) {
  108. destroy_handles();
  109. if(mdb.read.dbh){
  110. mdb.read.dbf.close(mdb.read.dbh);
  111. }
  112. if(mdb.write.dbh){
  113. mdb.write.dbf.close(mdb.write.dbh);
  114. }
  115. return;
  116. }
  117. int db_handle_error(ul_db_handle_t * handle, int no) {
  118. int query_len;
  119. ul_db_t * db;
  120. int i;
  121. str tmp;
  122. if(!handle){
  123. LM_ERR("NULL pointer in parameter.\n");
  124. return -1;
  125. }
  126. if(!db_master_write){
  127. return 0;
  128. }
  129. query_len = 35 + reg_table.len
  130. + error_col.len * 2 + id_col.len;
  131. if(query_len > UL_DB_QUERY_LEN){
  132. LM_ERR("query too long\n");
  133. return -1;
  134. }
  135. if((db = get_db_by_num(handle, no)) == NULL){
  136. LM_ERR("can't get db.\n");
  137. return -1;
  138. }
  139. if (sprintf(query, "UPDATE %.*s "
  140. "SET %.*s=%.*s+1 "
  141. "WHERE %.*s=%i "
  142. "AND %.*s=%i",
  143. reg_table.len, reg_table.s,
  144. error_col.len, error_col.s, error_col.len, error_col.s,
  145. id_col.len, id_col.s, handle->id,
  146. num_col.len, num_col.s, db->no) < 0) {
  147. LM_ERR("could not print the query\n");
  148. return -1;
  149. }
  150. tmp.s = query;
  151. tmp.len = strlen(query);
  152. if (mdb.write.dbf.raw_query (mdb.write.dbh, &tmp, NULL)) {
  153. LM_ERR("error in database update.\n");
  154. return -1;
  155. }
  156. for(i=0; i<DB_NUM; i++){
  157. if (handle->db[i].dbh && handle->db[i].dbf.close){
  158. handle->db[i].dbf.close(handle->db[i].dbh);
  159. handle->db[i].dbh = NULL;
  160. }
  161. }
  162. if(load_data(&mdb.read.dbf, mdb.read.dbh, &dbh_tmp, handle->id) < 0){
  163. LM_ERR("could not load id %i\n", handle->id);
  164. return -1;
  165. }
  166. refresh_handle(handle, &dbh_tmp, 0);
  167. LM_ERR("error on id %i, db %i, "
  168. "errors occured: %i, threshold: %i\n",
  169. handle->id, db->no, db->errors, db_error_threshold);
  170. if(db->errors >= db_error_threshold) {
  171. LM_DBG("db_handle_error: now doing failover");
  172. if((db_failover(&mdb.write.dbf, mdb.write.dbh, handle, no)) < 0) {
  173. LM_ERR("error in doing failover.\n");
  174. return -1;
  175. }
  176. if(load_data(&mdb.read.dbf, mdb.read.dbh, &dbh_tmp, handle->id) < 0){
  177. return -1;
  178. }
  179. refresh_handle(handle, &dbh_tmp, 0);
  180. set_must_refresh();
  181. }
  182. return 0;
  183. }
  184. int db_check_policy(int pol, int ok, int working) {
  185. #define DB_POL_N_1 0
  186. #define DB_POL_N_HALF 1
  187. #define DB_POL_N_ALL 2
  188. switch(policy) {
  189. case DB_POL_N_1:
  190. switch(pol) {
  191. case DB_POL_OP: if(ok >= (DB_NUM - 1)) {
  192. return 0;
  193. } else {
  194. return -1;
  195. }
  196. break;
  197. case DB_POL_QUERY: if(ok >= 1) {
  198. return 0;
  199. } else {
  200. return -1;
  201. }
  202. case DB_POL_MOD: if((ok == working) && (working >= (DB_NUM - 1))) {
  203. return 0;
  204. } else {
  205. return -1;
  206. }
  207. default: LM_ERR("wrong mode given.\n");
  208. return -1;
  209. }
  210. case DB_POL_N_HALF:
  211. switch(pol) {
  212. case DB_POL_OP: if(ok >= (DB_NUM / 2)) {
  213. return 0;
  214. } else {
  215. return -1;
  216. }
  217. break;
  218. case DB_POL_QUERY: if(ok >= 1) {
  219. return 0;
  220. } else {
  221. return -1;
  222. }
  223. case DB_POL_MOD: if((ok == working) && (working >= (DB_NUM / 2))) {
  224. return 0;
  225. } else {
  226. return -1;
  227. }
  228. default: LM_ERR("wrong mode given.\n");
  229. return -1;
  230. }
  231. case DB_POL_N_ALL:
  232. switch(pol) {
  233. case DB_POL_OP: if(ok == DB_NUM) {
  234. return 0;
  235. } else {
  236. return -1;
  237. }
  238. break;
  239. case DB_POL_QUERY: if(ok >= 1) {
  240. return 0;
  241. } else {
  242. return -1;
  243. }
  244. case DB_POL_MOD: if(ok == DB_NUM) {
  245. return 0;
  246. } else {
  247. return -1;
  248. }
  249. default: LM_ERR("wrong mode given.\n");
  250. return -1;
  251. }
  252. default:
  253. return -1;
  254. }
  255. }
  256. int ul_db_insert(str * table, str * first, str * second,
  257. db_key_t* _k, db_val_t* _v, int _n) {
  258. ul_db_handle_t * handle;
  259. if(!db_write){
  260. LM_ERR("not allowed in read only mode, abort.\n");
  261. return -1;
  262. }
  263. if((handle = get_handle(&mdb.read.dbf, mdb.read.dbh, first, second)) == NULL) {
  264. LM_ERR("could not retrieve db handle.\n");
  265. return -1;
  266. }
  267. return db_insert(handle, table, _k, _v, _n);
  268. }
  269. int ul_db_replace(str * table, str * first, str * second,
  270. db_key_t* _k, db_val_t* _v, int _n, int _un) {
  271. ul_db_handle_t * handle;
  272. if(!db_write){
  273. LM_ERR("not allowed in read only mode, abort.\n");
  274. return -1;
  275. }
  276. if((handle = get_handle(&mdb.read.dbf, mdb.read.dbh, first, second)) == NULL) {
  277. LM_ERR("could not retrieve db handle.\n");
  278. return -1;
  279. }
  280. return db_replace(handle, table, _k, _v, _n, _un);
  281. }
  282. int ul_db_update(str * table, str * first, str * second,
  283. db_key_t* _k, db_op_t * _op, db_val_t* _v,
  284. db_key_t* _uk, db_val_t* _uv, int _n, int _un) {
  285. ul_db_handle_t * handle;
  286. if(!db_write){
  287. LM_ERR("not allowed in read only mode, abort.\n");
  288. return -1;
  289. }
  290. if((handle = get_handle(&mdb.read.dbf, mdb.read.dbh, first, second)) == NULL) {
  291. LM_ERR("could not retrieve db handle.\n");
  292. return -1;
  293. }
  294. return db_update(handle, table, _k, _op, _v, _uk, _uv, _n, _un);
  295. }
  296. int ul_db_insert_update(str * table, str * first, str * second,
  297. db_key_t* _k, db_val_t* _v, int _n) {
  298. ul_db_handle_t * handle;
  299. if(!db_write){
  300. LM_ERR("not allowed in read only mode, abort.\n");
  301. return -1;
  302. }
  303. if((handle = get_handle(&mdb.read.dbf, mdb.read.dbh, first, second)) == NULL) {
  304. LM_ERR("could not retrieve db handle.\n");
  305. return -1;
  306. }
  307. return db_insert_update(handle, table, _k, _v, _n);
  308. }
  309. int ul_db_delete(str * table, str * first, str * second,
  310. db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n) {
  311. ul_db_handle_t * handle;
  312. if(!db_write){
  313. LM_ERR("not allowed in read only mode, abort.\n");
  314. return -1;
  315. }
  316. if((handle = get_handle(&mdb.read.dbf, mdb.read.dbh, first, second)) == NULL) {
  317. LM_ERR("could not retrieve db handle.\n");
  318. return -1;
  319. }
  320. return db_delete(handle, table, _k, _o, _v, _n);
  321. }
  322. int ul_db_query(str * table, str * first, str * second, db1_con_t *** _r_h,
  323. db_key_t* _k, db_op_t* _op, db_val_t* _v,
  324. db_key_t* _c, int _n, int _nc, db_key_t _o, db1_res_t** _r) {
  325. ul_db_handle_t * handle;
  326. db_func_t * f;
  327. int ret;
  328. if((handle = get_handle(&mdb.read.dbf, mdb.read.dbh, first, second)) == NULL) {
  329. LM_ERR("could not retrieve db handle.\n");
  330. return -1;
  331. }
  332. if((ret = db_query(handle, _r_h, &f, table, _k, _op, _v, _c, _n, _nc, _o, _r, db_master_write)) < 0){
  333. return ret;
  334. }
  335. add_dbf(*_r, f);
  336. return ret;
  337. }
  338. int ul_db_free_result(db1_con_t ** dbh, db1_res_t * res){
  339. db_func_t * f;
  340. if(!dbh){
  341. LM_ERR("NULL pointer in parameter.\n");
  342. return -1;
  343. }
  344. if((f = get_and_remove_dbf(res)) == NULL){
  345. return -1;
  346. }
  347. return f->free_result(*dbh, res);
  348. }
  349. int db_reactivate(ul_db_handle_t * handle, int no){
  350. if(!db_master_write){
  351. LM_ERR("running in read only mode, abort.\n");
  352. return -1;
  353. }
  354. return db_failover_reactivate(&mdb.write.dbf, mdb.write.dbh, handle, no);
  355. }
  356. int db_reset_failover_time(ul_db_handle_t * handle, int no){
  357. if(!db_master_write){
  358. LM_ERR("running in read only mode, abort.\n");
  359. return -1;
  360. }
  361. return db_failover_reset(&mdb.write.dbf, mdb.write.dbh, handle->id, no);
  362. }
  363. int ul_db_check(ul_db_handle_t * handle){
  364. if(db_master_write){
  365. return check_handle(&mdb.write.dbf, mdb.write.dbh, handle);
  366. } else {
  367. LM_ERR("checking is useless in read-only mode\n");
  368. return 0;
  369. }
  370. }
  371. static int add_dbf(db1_res_t * res, db_func_t * dbf){
  372. int i=0;
  373. for(i=0;i<UL_DB_RES_LIMIT;i++){
  374. if(!results[i].res){
  375. results[i].res = res;
  376. results[i].dbf = dbf;
  377. return 0;
  378. }
  379. }
  380. LM_ERR("no free dbf tmp mem, maybe forgotten to cleanup result sets?\n");
  381. return -1;
  382. }
  383. static db_func_t * get_and_remove_dbf(db1_res_t * res){
  384. int i=0;
  385. db_func_t * f;
  386. for(i=0; i<UL_DB_RES_LIMIT; i++){
  387. if(results[i].res == res){
  388. f = results[i].dbf;
  389. memset(&results[i], 0, sizeof(db_dbf_dbres_t));
  390. return f;
  391. }
  392. }
  393. LM_ERR("weird: dbf not found\n");
  394. return NULL;
  395. }