src/modules/ims_charging/ro_db_handler.c
efcd3421
 #include "ro_db_handler.h"
 #include "../../lib/srdb1/db.h"
 
 static db1_con_t* ro_db_handle = 0; /* database connection handle */
 static db_func_t ro_dbf;
 
 str ro_session_table_name = str_init(RO_SESSION_TABLE_NAME);
 str id_column = str_init(ID_COL);
 str h_entry_column = str_init(HASH_ENTRY_COL);
 str h_id_column = str_init(HASH_ID_COL);
 str session_id_column = str_init(SESSION_ID_COL);
 str dlg_h_entry_column = str_init(DLG_HASH_ENTRY_COL);
 str dlg_h_id_column = str_init(DLG_HASH_ID_COL);
 str direction_column = str_init(DIRECTION_COL);
 str asserted_column = str_init(ASSERTED_ID_COL);
 str callee_column = str_init(CALLEE_COL);
 str start_time_col = str_init(START_TIME_COL);
 str last_event_ts_column = str_init(LAST_EVENT_TS_COL);
 str reserved_sec_column = str_init(RESERVED_SECS_COL);
 str valid_for_column = str_init(VALID_FOR_COL);
 str state_column = str_init(STATE_COL);
63abc6f8
 str incoming_trunk_id_column = str_init(INCOMING_TRUNK_ID_COL);
 str outgoing_trunk_id_column = str_init(OUTGOING_TRUNK_ID_COL);
46e5cc86
 str rating_group_column = str_init(RATING_GROUP_COL);
 str service_identifier_column = str_init(SERVICE_IDENTIFIER_COL);
efcd3421
 
 typedef enum ro_session_field_idx {
     ID_COL_IDX = 0,
     HASH_ENTRY_COL_IDX,
     HASH_ID_COL_IDX,
     SESSION_ID_COL_IDX,
     DLG_HASH_ENTRY_COL_IDX,
     DLG_HASH_ID_COL_IDX,
     DIRECTION_COL_IDX,
     ASSERTED_ID_COL_IDX,
     CALLEE_COL_IDX,
     START_TIME_COL_IDX,
     LAST_EVENT_TS_COL_IDX,
     RESERVED_SECS_COL_IDX,
     VALID_FOR_COL_IDX,
46e5cc86
     STATE_COL_IDX,
63abc6f8
     INCOMING_TRUNK_ID_COL_IDX,
     OUTGOING_TRUNK_ID_COL_IDX,
46e5cc86
     RATING_GROUP_COL_IDX,
     SERVICE_IDENTIFIER_COL_IDX
 	    
efcd3421
 } ro_session_field_idx_t;
 
 #define GET_FIELD_IDX(_val, _idx)\
 		(_val + _idx)
 
 #define SET_STR_VALUE(_val, _str)\
 	do{\
 			VAL_STR((_val)).s = (_str).s;\
 			VAL_STR((_val)).len = (_str).len;\
 	}while(0);
 
 #define SET_NULL_FLAG(_vals, _i, _max, _flag)\
 	do{\
 		for((_i) = 0;(_i)<(_max); (_i)++)\
 			VAL_NULL((_vals)+(_i)) = (_flag);\
 	}while(0);
 
 #define SET_PROPER_NULL_FLAG(_str, _vals, _index)\
 	do{\
 		if( (_str).len == 0)\
 			VAL_NULL( (_vals)+(_index) ) = 1;\
 		else\
 			VAL_NULL( (_vals)+(_index) ) = 0;\
 	}while(0);
 
 #define GET_STR_VALUE(_res, _values, _index, _not_null, _unref)\
 	do{\
 		if (VAL_NULL((_values)+ (_index))) { \
 			if (_not_null) {\
 				if (_unref) unref_dlg(dlg,1);\
 				goto next_dialog; \
 			} else { \
 				(_res).s = 0; \
 				(_res).len = 0; \
 			}\
 		} else { \
 			(_res).s = VAL_STR((_values)+ (_index)).s;\
 			(_res).len = strlen(VAL_STR((_values)+ (_index)).s);\
 		} \
 	}while(0);
 
 int init_ro_db(const str *db_url, int dlg_hash_size, int db_update_period, int fetch_num_rows) {
     /* Find a database module */
     if (db_bind_mod(db_url, &ro_dbf) < 0) {
 	LM_ERR("Unable to bind to a database driver\n");
 	return -1;
     }
 
     if (ro_connect_db(db_url) != 0) {
 	LM_ERR("unable to connect to the database\n");
 	return -1;
     }
 
     if (db_check_table_version(&ro_dbf, ro_db_handle, &ro_session_table_name, RO_TABLE_VERSION) < 0) {
47d9d132
 	DB_TABLE_VERSION_ERROR(ro_session_table_name);
 	goto dberror;
efcd3421
     }
 
     //	if( (dlg_db_mode==DB_MODE_DELAYED) && 
     //	(register_timer( dialog_update_db, 0, db_update_period)<0 )) {
     //		LM_ERR("failed to register update db\n");
     //		return -1;
     //	}
 
     if ((load_ro_info_from_db(dlg_hash_size, fetch_num_rows)) != 0) {
 	LM_ERR("unable to load the dialog data\n");
47d9d132
 	goto dberror;
efcd3421
     }
 
     ro_dbf.close(ro_db_handle);
     ro_db_handle = 0;
 
     return 0;
47d9d132
 
 dberror:
     ro_dbf.close(ro_db_handle);
     ro_db_handle = 0;
     return -1;
efcd3421
 }
 
 int load_ro_info_from_db(int hash_size, int fetch_num_rows) {
508786fc
     LM_WARN("not supported yet\n");
efcd3421
     return 0;
 }
 
 int ro_connect_db(const str *db_url) {
     if (ro_db_handle) {
 	LM_CRIT("BUG - db connection found already open\n");
 	return -1;
     }
     if ((ro_db_handle = ro_dbf.init(db_url)) == 0)
 	return -1;
 
     /* use default table */
     if (ro_dbf.use_table(ro_db_handle, &ro_session_table_name) != 0) {
 	LM_ERR("Error in use table for table name [%.*s]\n", ro_session_table_name.len, ro_session_table_name.s);
 	return -1;
     }
 
     return 0;
 }
 
 void db_set_int_val(db_val_t* values, int index, int val) {
     VAL_TYPE(GET_FIELD_IDX(values, index)) = DB1_INT;
     VAL_NULL(GET_FIELD_IDX(values, index)) = 0;
     VAL_INT(GET_FIELD_IDX(values, index)) = val;
 }
 
 void db_set_str_val(db_val_t* values, int index, str* val) {
     VAL_TYPE(GET_FIELD_IDX(values, index)) = DB1_STR;
     VAL_NULL(GET_FIELD_IDX(values, index)) = 0;
     SET_STR_VALUE(GET_FIELD_IDX(values, index), *val);
 }
 
 void db_set_datetime_val(db_val_t* values, int index, time_t val) {
     VAL_TYPE(GET_FIELD_IDX(values, index)) = DB1_DATETIME;
     VAL_NULL(GET_FIELD_IDX(values, index)) = 0;
     VAL_TIME(GET_FIELD_IDX(values, index)) = val;
 }
 
 int update_ro_dbinfo_unsafe(struct ro_session* ro_session) {
     if ((ro_session->flags & RO_SESSION_FLAG_NEW) != 0 && (ro_session->flags & RO_SESSION_FLAG_INSERTED) == 0) {
 
 	db_val_t values[RO_SESSION_TABLE_COL_NUM];
 	db_key_t insert_keys[RO_SESSION_TABLE_COL_NUM] = {
 	    &id_column, &h_entry_column, &h_id_column, &session_id_column, &dlg_h_entry_column, &dlg_h_id_column,
 	    &direction_column, &asserted_column, &callee_column, &start_time_col, &last_event_ts_column,
63abc6f8
 	    &reserved_sec_column, &valid_for_column, &state_column, &incoming_trunk_id_column, &outgoing_trunk_id_column, &rating_group_column, &service_identifier_column
efcd3421
 	};
 
 	VAL_TYPE(GET_FIELD_IDX(values, ID_COL_IDX)) = DB1_INT;
 	VAL_NULL(GET_FIELD_IDX(values, ID_COL_IDX)) = 1;
 
 	db_set_int_val(values, HASH_ENTRY_COL_IDX, ro_session->h_entry);
 	db_set_int_val(values, HASH_ID_COL_IDX, ro_session->h_id);
 	db_set_str_val(values, SESSION_ID_COL_IDX, &ro_session->ro_session_id);
 	db_set_int_val(values, DLG_HASH_ENTRY_COL_IDX, ro_session->dlg_h_entry);
 	db_set_int_val(values, DLG_HASH_ID_COL_IDX, ro_session->dlg_h_id);
 	db_set_int_val(values, DIRECTION_COL_IDX, ro_session->direction);
 	db_set_str_val(values, ASSERTED_ID_COL_IDX, &ro_session->asserted_identity);
 	db_set_str_val(values, CALLEE_COL_IDX, &ro_session->called_asserted_identity);
88a7b00c
 	db_set_datetime_val(values, START_TIME_COL_IDX, ro_session->start_time/1000000);
 	db_set_datetime_val(values, LAST_EVENT_TS_COL_IDX, ro_session->last_event_timestamp/1000000);
efcd3421
 	db_set_int_val(values, RESERVED_SECS_COL_IDX, ro_session->reserved_secs);
 	db_set_int_val(values, VALID_FOR_COL_IDX, ro_session->valid_for);
 	db_set_int_val(values, STATE_COL_IDX, ro_session->active);
63abc6f8
 	db_set_str_val(values, INCOMING_TRUNK_ID_COL_IDX, &ro_session->incoming_trunk_id);
 	db_set_str_val(values, OUTGOING_TRUNK_ID_COL_IDX, &ro_session->outgoing_trunk_id);
46e5cc86
 	db_set_int_val(values, RATING_GROUP_COL_IDX, ro_session->rating_group);
 	db_set_int_val(values, SERVICE_IDENTIFIER_COL_IDX, ro_session->service_identifier);
 	
efcd3421
 
 	LM_DBG("Inserting ro_session into database\n");
 	if ((ro_dbf.insert(ro_db_handle, insert_keys, values, RO_SESSION_TABLE_COL_NUM)) != 0) {
 	    LM_ERR("could not add new Ro session into DB.... continuing\n");
 	    goto error;
 	}
 	ro_session->flags &= ~(RO_SESSION_FLAG_NEW | RO_SESSION_FLAG_CHANGED);
 	ro_session->flags |= RO_SESSION_FLAG_INSERTED;
 
     } else if ((ro_session->flags & RO_SESSION_FLAG_CHANGED) != 0 && (ro_session->flags & RO_SESSION_FLAG_INSERTED) != 0) {
 
46e5cc86
 	db_val_t values[RO_SESSION_TABLE_COL_NUM-1];
 	db_key_t update_keys[RO_SESSION_TABLE_COL_NUM-1] = {
efcd3421
 	    &h_entry_column, &h_id_column, &session_id_column, &dlg_h_entry_column, &dlg_h_id_column,
 	    &direction_column, &asserted_column, &callee_column, &start_time_col, &last_event_ts_column,
63abc6f8
 	    &reserved_sec_column, &valid_for_column, &state_column, &incoming_trunk_id_column, &outgoing_trunk_id_column, &rating_group_column, &service_identifier_column
efcd3421
 	};
 
 	db_set_int_val(values, HASH_ENTRY_COL_IDX - 1, ro_session->h_entry);
 	db_set_int_val(values, HASH_ID_COL_IDX - 1, ro_session->h_id);
 	db_set_str_val(values, SESSION_ID_COL_IDX - 1, &ro_session->ro_session_id);
 	db_set_int_val(values, DLG_HASH_ENTRY_COL_IDX - 1, ro_session->dlg_h_entry);
 	db_set_int_val(values, DLG_HASH_ID_COL_IDX - 1, ro_session->dlg_h_id);
 	db_set_int_val(values, DIRECTION_COL_IDX - 1, ro_session->direction);
 	db_set_str_val(values, ASSERTED_ID_COL_IDX - 1, &ro_session->asserted_identity);
 	db_set_str_val(values, CALLEE_COL_IDX - 1, &ro_session->called_asserted_identity);
88a7b00c
 	db_set_datetime_val(values, START_TIME_COL_IDX - 1, ro_session->start_time/1000000);
 	db_set_datetime_val(values, LAST_EVENT_TS_COL_IDX - 1, ro_session->last_event_timestamp/1000000);
efcd3421
 	db_set_int_val(values, RESERVED_SECS_COL_IDX - 1, ro_session->reserved_secs);
 	db_set_int_val(values, VALID_FOR_COL_IDX - 1, ro_session->valid_for);
 	db_set_int_val(values, STATE_COL_IDX - 1, ro_session->active);
63abc6f8
 	db_set_str_val(values, INCOMING_TRUNK_ID_COL_IDX - 1, &ro_session->incoming_trunk_id);
 	db_set_str_val(values, OUTGOING_TRUNK_ID_COL_IDX - 1, &ro_session->outgoing_trunk_id);
46e5cc86
 	db_set_int_val(values, RATING_GROUP_COL_IDX - 1, ro_session->rating_group);
 	db_set_int_val(values, SERVICE_IDENTIFIER_COL_IDX - 1, ro_session->service_identifier);
efcd3421
 
 	LM_DBG("Updating ro_session in database\n");
 	if ((ro_dbf.update(ro_db_handle, update_keys/*match*/, 0/*match*/, values/*match*/, update_keys/*update*/, values/*update*/, 3/*match*/, 13/*update*/)) != 0) {
 	    LM_ERR("could not update Ro session information in DB... continuing\n");
 	    goto error;
 	}
 	ro_session->flags &= ~RO_SESSION_FLAG_CHANGED;
     } else if ((ro_session->flags & RO_SESSION_FLAG_DELETED) != 0) {
 	db_val_t values[3];
 	db_key_t match_keys[3] = {&h_entry_column, &h_id_column, &session_id_column};
 	
 	db_set_int_val(values, HASH_ENTRY_COL_IDX - 1, ro_session->h_entry);
 	db_set_int_val(values, HASH_ID_COL_IDX - 1, ro_session->h_id);
 	db_set_str_val(values, SESSION_ID_COL_IDX - 1, &ro_session->ro_session_id);
 	
 	if(ro_dbf.delete(ro_db_handle, match_keys, 0, values, 3) < 0) {
 		LM_ERR("failed to delete ro session database information... continuing\n");
 		return -1;
 	}
     } else {
 	LM_WARN("Asked to update Ro session in strange state [%d]\n", ro_session->flags);
     }
 
     return 0;
 
 error:
     return -1;
 }
 
 int update_ro_dbinfo(struct ro_session* ro_session) {
     struct ro_session_entry entry;
     /* lock the entry */
     entry = (ro_session_table->entries)[ro_session->h_entry];
     ro_session_lock(ro_session_table, &entry);
     if (update_ro_dbinfo_unsafe(ro_session) != 0) {
 	LM_ERR("failed to update ro_session in DB\n");
 	ro_session_unlock(ro_session_table, &entry);
 	return -1;
     }
     ro_session_unlock(ro_session_table, &entry);
     return 0;
 }