diff --git a/src/modules/p_usrloc/doc/p_usrloc_admin.xml b/src/modules/p_usrloc/doc/p_usrloc_admin.xml index 4bfe7672bb8..8c109280ae3 100644 --- a/src/modules/p_usrloc/doc/p_usrloc_admin.xml +++ b/src/modules/p_usrloc/doc/p_usrloc_admin.xml @@ -501,6 +501,26 @@ modparam("p_usrloc", "db_transaction_level", "READ UNCOMMITED") ... modparam("p_usrloc", "write_on_master_db", "0") ... + + + + +
+ <varname>mdb_availability_control</varname>(str) + + Checks the master database in certain time intervals specified by the retry_interval parameter. Overwrites the write_on_master_db parameter based on the reachability of master database. If the master db is unavailable then the aforementioned parameter will be deactivated. + + + + Default value is 0. + + + + Set <varname>mdb_availability_control</varname> parameter + +... +modparam("p_usrloc", "mdb_availability_control", 1) +...
diff --git a/src/modules/p_usrloc/p_usrloc_mod.c b/src/modules/p_usrloc/p_usrloc_mod.c index 21d78785e97..8ed0ec83900 100644 --- a/src/modules/p_usrloc/p_usrloc_mod.c +++ b/src/modules/p_usrloc/p_usrloc_mod.c @@ -165,6 +165,7 @@ int policy = DB_DEFAULT_POLICY; int db_write = 0; int db_master_write = 0; int alg_location = 0; +int mdb_availability_control = 0; int db_use_transactions = 0; str db_transaction_level = str_init(DB_DEFAULT_TRANSACTION_LEVEL); @@ -182,7 +183,7 @@ str default_db_type = str_init(DEFAULT_DB_TYPE); str domain_db = str_init(DEFAULT_DOMAIN_DB); int default_dbt = 0; int expire = 0; - +db_shared_param_t *write_on_master_db_shared; /*! \brief * Exported functions @@ -248,6 +249,7 @@ static param_export_t params[] = { {"alg_location", INT_PARAM, &alg_location }, {"db_ops_ruid", INT_PARAM, &default_p_usrloc_cfg.db_ops_ruid}, {"db_update_as_insert", INT_PARAM, &default_p_usrloc_cfg.db_update_as_insert}, + {"mdb_availability_control", INT_PARAM, &mdb_availability_control}, {0, 0, 0} }; @@ -307,6 +309,13 @@ static int mod_init(void) } #endif + if((write_on_master_db_shared = shm_malloc(sizeof(db_shared_param_t))) == NULL) { + LM_ERR("couldn't allocate shared memory.\n"); + return -1; + } else { + write_on_master_db_shared->val = db_master_write; + } + if(ul_hash_size<=1) ul_hash_size = 512; else @@ -395,10 +404,14 @@ static int mod_init(void) LM_ERR("could not init database watch environment.\n"); return -1; } - if(db_master_write){ + if (lock_init(&write_on_master_db_shared->lock)==0){ + LM_ERR("could not initialise lock\n"); + } + if(write_on_master_db_shared->val){ /* register extra dummy timer to be created in init_db_check() */ register_dummy_timers(1); } + check_master_db(db_master_write); return 0; } diff --git a/src/modules/p_usrloc/p_usrloc_mod.h b/src/modules/p_usrloc/p_usrloc_mod.h index 1492de994de..eececd93afc 100644 --- a/src/modules/p_usrloc/p_usrloc_mod.h +++ b/src/modules/p_usrloc/p_usrloc_mod.h @@ -123,5 +123,11 @@ extern int connection_expires; extern int alg_location; extern int max_loc_nr; +typedef struct db_shared_param { + int val; + gen_lock_t lock; +} db_shared_param_t; +extern db_shared_param_t *write_on_master_db_shared; +extern int mdb_availability_control; #endif /* UL_MOD_H */ diff --git a/src/modules/p_usrloc/ul_db.c b/src/modules/p_usrloc/ul_db.c index 9e5efbe91a6..eeb0ec21bf1 100644 --- a/src/modules/p_usrloc/ul_db.c +++ b/src/modules/p_usrloc/ul_db.c @@ -60,7 +60,7 @@ int ul_db_init(void) { memset(results, 0, sizeof(results)); - if(db_master_write){ + if(write_on_master_db_shared->val){ if(db_bind_mod(mdb.write.url, &mdb.write.dbf) < 0) { LM_ERR("could not bind api for write db.\n"); return -1; @@ -102,13 +102,16 @@ int ul_db_child_init(void) { if(ul_db_child_locnr_init() == -1) return -1; LM_INFO("location number is %d\n", max_loc_nr); - if(db_master_write){ + lock_get(&write_on_master_db_shared->lock); + if(write_on_master_db_shared->val){ if((mdb.write.dbh = mdb.write.dbf.init(mdb.write.url)) == NULL) { LM_ERR("could not connect to sip master db (write).\n"); + lock_release(&write_on_master_db_shared->lock); return -1; } LM_INFO("write db connection for children initialized"); } + lock_release(&write_on_master_db_shared->lock); return 0; } @@ -146,10 +149,13 @@ int db_handle_error(ul_db_handle_t * handle, int no) { LM_ERR("NULL pointer in parameter.\n"); return -1; } - - if(!db_master_write){ + + lock_get(&write_on_master_db_shared->lock); + if(!write_on_master_db_shared->val){ + lock_release(&write_on_master_db_shared->lock); return 0; } + lock_release(&write_on_master_db_shared->lock); query_len = 35 + reg_table.len + error_col.len * 2 + id_col.len; @@ -372,9 +378,12 @@ int ul_db_query(str * table, str * first, str * second, db1_con_t *** _r_h, 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){ + lock_get(&write_on_master_db_shared->lock); + if((ret = db_query(handle, _r_h, &f, table, _k, _op, _v, _c, _n, _nc, _o, _r, write_on_master_db_shared->val)) < 0){ + lock_release(&write_on_master_db_shared->lock); return ret; } + lock_release(&write_on_master_db_shared->lock); add_dbf(*_r, f); return ret; } @@ -392,25 +401,34 @@ int ul_db_free_result(db1_con_t ** dbh, db1_res_t * res){ } int db_reactivate(ul_db_handle_t * handle, int no){ - if(!db_master_write){ + lock_get(&write_on_master_db_shared->lock); + if(!write_on_master_db_shared->val){ + lock_release(&write_on_master_db_shared->lock); LM_ERR("running in read only mode, abort.\n"); return -1; } + lock_release(&write_on_master_db_shared->lock); 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){ + lock_get(&write_on_master_db_shared->lock); + if(!write_on_master_db_shared->val){ + lock_release(&write_on_master_db_shared->lock); LM_ERR("running in read only mode, abort.\n"); return -1; } + lock_release(&write_on_master_db_shared->lock); 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){ + lock_get(&write_on_master_db_shared->lock); + if(write_on_master_db_shared->val){ + lock_release(&write_on_master_db_shared->lock); return check_handle(&mdb.write.dbf, mdb.write.dbh, handle); } else { + lock_release(&write_on_master_db_shared->lock); LM_ERR("checking is useless in read-only mode\n"); return 0; } diff --git a/src/modules/p_usrloc/ul_db.h b/src/modules/p_usrloc/ul_db.h index 40ae8274fbc..1cdf7a61604 100644 --- a/src/modules/p_usrloc/ul_db.h +++ b/src/modules/p_usrloc/ul_db.h @@ -56,6 +56,7 @@ typedef struct ul_master_db_set { } ul_master_db_set_t; extern int required_caps; +extern ul_master_db_set_t mdb; int ul_db_init(); diff --git a/src/modules/p_usrloc/ul_db_watch.c b/src/modules/p_usrloc/ul_db_watch.c index d736f942c92..3f5edfc57fd 100644 --- a/src/modules/p_usrloc/ul_db_watch.c +++ b/src/modules/p_usrloc/ul_db_watch.c @@ -96,7 +96,10 @@ void check_dbs(unsigned int ticks, void *param){ ul_db_handle_list_t * tmp2, * new_element; int found; int i; - + + if(mdb_availability_control) { + check_master_db(db_master_write); + } if(!list_lock){ return; } @@ -149,6 +152,22 @@ void check_dbs(unsigned int ticks, void *param){ lock_release(list_lock); } +void check_master_db(int dbm_write_default) { + if(mdb.write.dbh){ + mdb.write.dbf.close(mdb.write.dbh); + mdb.write.dbh = NULL; + } + + lock_get(&write_on_master_db_shared->lock); + if((mdb.write.dbh = mdb.write.dbf.init(mdb.write.url)) == NULL) { + write_on_master_db_shared->val = 0; + LM_WARN("Master db is unavailable.\n"); + } else { + write_on_master_db_shared->val = dbm_write_default; + } + lock_release(&write_on_master_db_shared->lock); +} + int ul_register_watch_db(int id){ ul_db_watch_list_t * new_id = NULL, * tmp; if(!list_lock){ diff --git a/src/modules/p_usrloc/ul_db_watch.h b/src/modules/p_usrloc/ul_db_watch.h index 22da88f1bd2..e779af547c1 100644 --- a/src/modules/p_usrloc/ul_db_watch.h +++ b/src/modules/p_usrloc/ul_db_watch.h @@ -35,4 +35,6 @@ int ul_register_watch_db(int id); int ul_unregister_watch_db(int id); +void check_master_db(int dbm_write_default); + #endif