123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440 |
- /* sp-ul_db module
- *
- * Copyright (C) 2007 1&1 Internet AG
- *
- * This file is part of Kamailio, a free SIP server.
- *
- * Kamailio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * Kamailio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #include "../../lib/srdb1/db.h"
- #include "ul_db.h"
- #include "p_usrloc_mod.h"
- #include "ul_db_failover.h"
- #include "ul_db_ins.h"
- #include "ul_db_repl.h"
- #include "ul_db_ins_upd.h"
- #include "ul_db_upd.h"
- #include "ul_db_del.h"
- #include "ul_db_query.h"
- #include "ul_check.h"
- #include <unistd.h>
- ul_db_handle_t dbh_tmp;
- ul_master_db_set_t mdb;
- int required_caps = DB_CAP_QUERY | DB_CAP_RAW_QUERY | DB_CAP_INSERT | DB_CAP_DELETE | DB_CAP_UPDATE | DB_CAP_INSERT_UPDATE;
- static char query[UL_DB_QUERY_LEN];
- typedef struct db_dbf_dbres {
- db1_res_t * res;
- db_func_t * dbf;
- } db_dbf_dbres_t;
- #define UL_DB_RES_LIMIT 20
- db_dbf_dbres_t results[UL_DB_RES_LIMIT];
- static int add_dbf(db1_res_t * res, db_func_t * dbf);
- static db_func_t * get_and_remove_dbf(db1_res_t * res);
- int ul_db_init(void) {
- mdb.read.url = &read_db_url;
- mdb.write.url = &write_db_url;
-
- memset(results, 0, sizeof(results));
- if(db_master_write){
- if(db_bind_mod(mdb.write.url, &mdb.write.dbf) < 0) {
- LM_ERR("could not bind api for write db.\n");
- return -1;
- }
- if(!(mdb.write.dbf.cap & required_caps)) {
- LM_ERR("db api of write db doesn't support required operation.\n");
- return -1;
- }
- LM_INFO("write db initialized");
- }
-
- if(db_bind_mod(mdb.read.url, &mdb.read.dbf) < 0) {
- LM_ERR("could not bind db api for read db.\n");
- return -1;
- }
- if(!(mdb.read.dbf.cap & required_caps)) {
- LM_ERR("db api of read db doesn't support required operation.\n");
- return -1;
- }
- LM_INFO("read db initialized");
- return 0;
- }
- int ul_db_child_init(void) {
- if(mdb.read.dbh){
- mdb.read.dbf.close(mdb.read.dbh);
- mdb.read.dbh = NULL;
- }
- if(mdb.write.dbh){
- mdb.write.dbf.close(mdb.write.dbh);
- mdb.write.dbh = NULL;
- }
- if((mdb.read.dbh = mdb.read.dbf.init(mdb.read.url)) == NULL) {
- LM_ERR("could not connect to sip master db (read).\n");
- return -1;
- }
- LM_INFO("read db connection for children initialized");
-
- if(ul_db_child_locnr_init() == -1) return -1;
-
- LM_INFO("location number is %d\n", max_loc_nr);
- if(db_master_write){
- if((mdb.write.dbh = mdb.write.dbf.init(mdb.write.url)) == NULL) {
- LM_ERR("could not connect to sip master db (write).\n");
- return -1;
- }
- LM_INFO("write db connection for children initialized");
- }
- return 0;
- }
- int ul_db_child_locnr_init(void) {
- if(!mdb.read.dbh){
- LM_ERR("Sip master DB connection(read) is down");
- return -1;
- }
- if(load_location_number(&mdb.read.dbf, mdb.read.dbh, &max_loc_nr) != 0){
- LM_ERR("could not load location number\n");
- return -1;
- }
- return 0;
- }
- void ul_db_shutdown(void) {
- destroy_handles();
- if(mdb.read.dbh){
- mdb.read.dbf.close(mdb.read.dbh);
- }
- if(mdb.write.dbh){
- mdb.write.dbf.close(mdb.write.dbh);
- }
- return;
- }
- int db_handle_error(ul_db_handle_t * handle, int no) {
- int query_len;
- ul_db_t * db;
- int i;
- str tmp;
-
- if(!handle){
- LM_ERR("NULL pointer in parameter.\n");
- return -1;
- }
-
- if(!db_master_write){
- return 0;
- }
- query_len = 35 + reg_table.len
- + error_col.len * 2 + id_col.len;
-
- if(query_len > UL_DB_QUERY_LEN){
- LM_ERR("query too long\n");
- return -1;
- }
-
- if((db = get_db_by_num(handle, no)) == NULL){
- LM_ERR("can't get db.\n");
- return -1;
- }
-
- if (sprintf(query, "UPDATE %.*s "
- "SET %.*s=%.*s+1 "
- "WHERE %.*s=%i "
- "AND %.*s=%i",
- reg_table.len, reg_table.s,
- error_col.len, error_col.s, error_col.len, error_col.s,
- id_col.len, id_col.s, handle->id,
- num_col.len, num_col.s, db->no) < 0) {
- LM_ERR("could not print the query\n");
- return -1;
- }
- tmp.s = query;
- tmp.len = strlen(query);
- if (mdb.write.dbf.raw_query (mdb.write.dbh, &tmp, NULL)) {
- LM_ERR("error in database update.\n");
- return -1;
- }
-
- for(i=0; i<DB_NUM; i++){
- if (handle->db[i].dbh && handle->db[i].dbf.close){
- handle->db[i].dbf.close(handle->db[i].dbh);
- handle->db[i].dbh = NULL;
- }
- }
- if(load_data(&mdb.read.dbf, mdb.read.dbh, &dbh_tmp, handle->id) < 0){
- LM_ERR("could not load id %i\n", handle->id);
- return -1;
- }
- refresh_handle(handle, &dbh_tmp, 0);
- LM_ERR("error on id %i, db %i, "
- "errors occured: %i, threshold: %i\n",
- handle->id, db->no, db->errors, db_error_threshold);
- if(db->errors >= db_error_threshold) {
- LM_DBG("db_handle_error: now doing failover");
- if((db_failover(&mdb.write.dbf, mdb.write.dbh, handle, no)) < 0) {
- LM_ERR("error in doing failover.\n");
- return -1;
- }
- if(load_data(&mdb.read.dbf, mdb.read.dbh, &dbh_tmp, handle->id) < 0){
- return -1;
- }
- refresh_handle(handle, &dbh_tmp, 0);
- set_must_refresh();
- }
- return 0;
- }
- int db_check_policy(int pol, int ok, int working) {
- #define DB_POL_N_1 0
- #define DB_POL_N_HALF 1
- #define DB_POL_N_ALL 2
- switch(policy) {
- case DB_POL_N_1:
- switch(pol) {
- case DB_POL_OP: if(ok >= (DB_NUM - 1)) {
- return 0;
- } else {
- return -1;
- }
- break;
- case DB_POL_QUERY: if(ok >= 1) {
- return 0;
- } else {
- return -1;
- }
- case DB_POL_MOD: if((ok == working) && (working >= (DB_NUM - 1))) {
- return 0;
- } else {
- return -1;
- }
- default: LM_ERR("wrong mode given.\n");
- return -1;
- }
- case DB_POL_N_HALF:
- switch(pol) {
- case DB_POL_OP: if(ok >= (DB_NUM / 2)) {
- return 0;
- } else {
- return -1;
- }
- break;
- case DB_POL_QUERY: if(ok >= 1) {
- return 0;
- } else {
- return -1;
- }
- case DB_POL_MOD: if((ok == working) && (working >= (DB_NUM / 2))) {
- return 0;
- } else {
- return -1;
- }
- default: LM_ERR("wrong mode given.\n");
- return -1;
- }
- case DB_POL_N_ALL:
- switch(pol) {
- case DB_POL_OP: if(ok == DB_NUM) {
- return 0;
- } else {
- return -1;
- }
- break;
- case DB_POL_QUERY: if(ok >= 1) {
- return 0;
- } else {
- return -1;
- }
- case DB_POL_MOD: if(ok == DB_NUM) {
- return 0;
- } else {
- return -1;
- }
- default: LM_ERR("wrong mode given.\n");
- return -1;
- }
- default:
- return -1;
- }
- }
- int ul_db_insert(str * table, str * first, str * second,
- db_key_t* _k, db_val_t* _v, int _n) {
- ul_db_handle_t * handle;
- if(!db_write){
- LM_ERR("not allowed in read only mode, abort.\n");
- return -1;
- }
- if((handle = get_handle(&mdb.read.dbf, mdb.read.dbh, first, second)) == NULL) {
- LM_ERR("could not retrieve db handle.\n");
- return -1;
- }
- return db_insert(handle, table, _k, _v, _n);
- }
- int ul_db_replace(str * table, str * first, str * second,
- db_key_t* _k, db_val_t* _v, int _n, int _un) {
- ul_db_handle_t * handle;
- if(!db_write){
- LM_ERR("not allowed in read only mode, abort.\n");
- return -1;
- }
- if((handle = get_handle(&mdb.read.dbf, mdb.read.dbh, first, second)) == NULL) {
- LM_ERR("could not retrieve db handle.\n");
- return -1;
- }
- return db_replace(handle, table, _k, _v, _n, _un);
- }
- int ul_db_update(str * table, str * first, str * second,
- db_key_t* _k, db_op_t * _op, db_val_t* _v,
- db_key_t* _uk, db_val_t* _uv, int _n, int _un) {
- ul_db_handle_t * handle;
- if(!db_write){
- LM_ERR("not allowed in read only mode, abort.\n");
- return -1;
- }
- if((handle = get_handle(&mdb.read.dbf, mdb.read.dbh, first, second)) == NULL) {
- LM_ERR("could not retrieve db handle.\n");
- return -1;
- }
- return db_update(handle, table, _k, _op, _v, _uk, _uv, _n, _un);
- }
- int ul_db_insert_update(str * table, str * first, str * second,
- db_key_t* _k, db_val_t* _v, int _n) {
- ul_db_handle_t * handle;
- if(!db_write){
- LM_ERR("not allowed in read only mode, abort.\n");
- return -1;
- }
- if((handle = get_handle(&mdb.read.dbf, mdb.read.dbh, first, second)) == NULL) {
- LM_ERR("could not retrieve db handle.\n");
- return -1;
- }
- return db_insert_update(handle, table, _k, _v, _n);
- }
- int ul_db_delete(str * table, str * first, str * second,
- db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n) {
- ul_db_handle_t * handle;
- if(!db_write){
- LM_ERR("not allowed in read only mode, abort.\n");
- return -1;
- }
- if((handle = get_handle(&mdb.read.dbf, mdb.read.dbh, first, second)) == NULL) {
- LM_ERR("could not retrieve db handle.\n");
- return -1;
- }
- return db_delete(handle, table, _k, _o, _v, _n);
- }
- int ul_db_query(str * table, str * first, str * second, db1_con_t *** _r_h,
- db_key_t* _k, db_op_t* _op, db_val_t* _v,
- db_key_t* _c, int _n, int _nc, db_key_t _o, db1_res_t** _r) {
- ul_db_handle_t * handle;
- db_func_t * f;
- int ret;
- if((handle = get_handle(&mdb.read.dbf, mdb.read.dbh, first, second)) == NULL) {
- LM_ERR("could not retrieve db handle.\n");
- return -1;
- }
- if((ret = db_query(handle, _r_h, &f, table, _k, _op, _v, _c, _n, _nc, _o, _r, db_master_write)) < 0){
- return ret;
- }
- add_dbf(*_r, f);
- return ret;
- }
- int ul_db_free_result(db1_con_t ** dbh, db1_res_t * res){
- db_func_t * f;
- if(!dbh){
- LM_ERR("NULL pointer in parameter.\n");
- return -1;
- }
- if((f = get_and_remove_dbf(res)) == NULL){
- return -1;
- }
- return f->free_result(*dbh, res);
- }
- int db_reactivate(ul_db_handle_t * handle, int no){
- if(!db_master_write){
- LM_ERR("running in read only mode, abort.\n");
- return -1;
- }
- return db_failover_reactivate(&mdb.write.dbf, mdb.write.dbh, handle, no);
- }
- int db_reset_failover_time(ul_db_handle_t * handle, int no){
- if(!db_master_write){
- LM_ERR("running in read only mode, abort.\n");
- return -1;
- }
- return db_failover_reset(&mdb.write.dbf, mdb.write.dbh, handle->id, no);
- }
- int ul_db_check(ul_db_handle_t * handle){
- if(db_master_write){
- return check_handle(&mdb.write.dbf, mdb.write.dbh, handle);
- } else {
- LM_ERR("checking is useless in read-only mode\n");
- return 0;
- }
- }
- static int add_dbf(db1_res_t * res, db_func_t * dbf){
- int i=0;
- for(i=0;i<UL_DB_RES_LIMIT;i++){
- if(!results[i].res){
- results[i].res = res;
- results[i].dbf = dbf;
- return 0;
- }
- }
- LM_ERR("no free dbf tmp mem, maybe forgotten to cleanup result sets?\n");
- return -1;
- }
- static db_func_t * get_and_remove_dbf(db1_res_t * res){
- int i=0;
- db_func_t * f;
- for(i=0; i<UL_DB_RES_LIMIT; i++){
- if(results[i].res == res){
- f = results[i].dbf;
- memset(&results[i], 0, sizeof(db_dbf_dbres_t));
- return f;
- }
- }
- LM_ERR("weird: dbf not found\n");
- return NULL;
- }
|