Skip to content

Commit

Permalink
cnxcc: release credit_data in terminate_all_calls
Browse files Browse the repository at this point in the history
- GH #563

(cherry picked from commit d0bdaa7)
  • Loading branch information
grumvalski committed Jun 6, 2016
1 parent 12b0480 commit 7a0de65
Showing 1 changed file with 69 additions and 5 deletions.
74 changes: 69 additions & 5 deletions modules/cnxcc/cnxcc_mod.c
Expand Up @@ -265,6 +265,13 @@ static int __mod_init(void) {
_data.channel.credit_data_by_client = shm_malloc(sizeof(struct str_hash_table));
_data.channel.call_data_by_cid = shm_malloc(sizeof(struct str_hash_table));

memset(_data.time.credit_data_by_client, 0, sizeof(struct str_hash_table));
memset(_data.time.call_data_by_cid, 0, sizeof(struct str_hash_table));
memset(_data.money.credit_data_by_client, 0, sizeof(struct str_hash_table));
memset(_data.money.call_data_by_cid, 0, sizeof(struct str_hash_table));
memset(_data.channel.credit_data_by_client, 0, sizeof(struct str_hash_table));
memset(_data.channel.call_data_by_cid, 0, sizeof(struct str_hash_table));

_data.stats = (stats_t *) shm_malloc(sizeof(stats_t));

if (!_data.stats) {
Expand Down Expand Up @@ -655,17 +662,19 @@ static void __stop_billing(str *callid) {
* Remove (and free) the call from the list of calls of the current credit_data
*/
clist_rm(call, next, prev);
/*
* don't free the call if all the credit data is being deallocated,
* it will be freed by terminate_all_calls()

/* return if credit_data is being deallocated.
* the call and the credit data will be freed by terminate_all_calls()
*/
if (!credit_data->deallocating) {
__free_call(call);
if (credit_data->deallocating) {
return;
}

__free_call(call);
/*
* In case there are no active calls for a certain client, we remove the client-id from the hash table.
* This way, we can save memory for useful clients.
*
*/
if (credit_data->number_of_calls == 0) {
LM_DBG("Removing client [%.*s] and its calls from the list\n", credit_data->call_list->client_id.len, credit_data->call_list->client_id.s);
Expand Down Expand Up @@ -882,9 +891,29 @@ static void __start_billing(str *callid, str *from_uri, str *to_uri, str tags[2]
}

// must be called with lock held on credit_data
/* terminate all calls and remove credit_data */
void terminate_all_calls(credit_data_t *credit_data) {
call_t *call = NULL,
*tmp = NULL;
struct str_hash_entry *cd_entry = NULL;
hash_tables_t *hts = NULL;

switch(credit_data->type) {
case CREDIT_MONEY:
hts = &_data.money;
break;
case CREDIT_TIME:
hts = &_data.time;
break;
case CREDIT_CHANNEL:
hts = &_data.channel;
break;
default:
LM_ERR("BUG: Something went terribly wrong\n");
return;
}

cd_entry = str_hash_get(hts->credit_data_by_client, credit_data->call_list->client_id.s, credit_data->call_list->client_id.len);

credit_data->deallocating = 1;

Expand All @@ -902,6 +931,36 @@ void terminate_all_calls(credit_data_t *credit_data) {
LM_WARN("invalid call structure %p\n", call);
}
}

cnxcc_lock(hts->lock);

if (_data.redis) {
redis_clean_up_if_last(credit_data);
shm_free(credit_data->str_id);
}

/*
* Remove the credit_data_t from the hash table
*/
str_hash_del(cd_entry);

cnxcc_unlock(hts->lock);

/*
* Free client_id in list's root
*/
shm_free(credit_data->call_list->client_id.s);
shm_free(credit_data->call_list);

/*
* Release the lock since we are going to free the entry down below
*/
cnxcc_unlock(credit_data->lock);

/*
* Free the whole entry
*/
__free_credit_data_hash_entry(cd_entry);
}

/*
Expand Down Expand Up @@ -1099,6 +1158,11 @@ static credit_data_t *__get_or_create_credit_data_entry(str *client_id, credit_t
static credit_data_t *__alloc_new_credit_data(str *client_id, credit_type_t type) {
credit_data_t *credit_data = shm_malloc(sizeof(credit_data_t));;

if (credit_data == NULL)
goto no_memory;

memset(credit_data, 0, sizeof(credit_data_t));

cnxcc_lock_init(credit_data->lock);

credit_data->call_list = shm_malloc(sizeof(call_t));
Expand Down

0 comments on commit 7a0de65

Please sign in to comment.