Browse code

cnxcc: release credit_data in terminate_all_calls

- GH #563

grumvalski authored on 05/06/2016 06:27:37
Showing 1 changed files
... ...
@@ -265,6 +265,13 @@ static int __mod_init(void) {
265 265
 	_data.channel.credit_data_by_client	= shm_malloc(sizeof(struct str_hash_table));
266 266
 	_data.channel.call_data_by_cid = shm_malloc(sizeof(struct str_hash_table));
267 267
 
268
+	memset(_data.time.credit_data_by_client, 0, sizeof(struct str_hash_table));
269
+	memset(_data.time.call_data_by_cid, 0, sizeof(struct str_hash_table));
270
+	memset(_data.money.credit_data_by_client, 0, sizeof(struct str_hash_table));
271
+	memset(_data.money.call_data_by_cid, 0, sizeof(struct str_hash_table));
272
+	memset(_data.channel.credit_data_by_client, 0, sizeof(struct str_hash_table));
273
+	memset(_data.channel.call_data_by_cid, 0, sizeof(struct str_hash_table));
274
+
268 275
 	_data.stats = (stats_t *) shm_malloc(sizeof(stats_t));
269 276
 
270 277
 	if (!_data.stats) {
... ...
@@ -655,17 +662,19 @@ static void __stop_billing(str *callid) {
655 655
 	 * Remove (and free) the call from the list of calls of the current credit_data
656 656
 	 */
657 657
 	clist_rm(call, next, prev);
658
-	/* 
659
-	 * don't free the call if all the credit data is being deallocated,
660
-	 * it will be freed by terminate_all_calls()
658
+	
659
+	/* return if credit_data is being deallocated.
660
+	 * the call and the credit data will be freed by terminate_all_calls()
661 661
 	 */
662
-	if (!credit_data->deallocating) {
663
-		__free_call(call);
662
+	if (credit_data->deallocating) {
663
+		return;
664 664
 	}
665 665
 
666
+	__free_call(call);
666 667
 	/*
667 668
 	 * In case there are no active calls for a certain client, we remove the client-id from the hash table.
668 669
 	 * This way, we can save memory for useful clients.
670
+	 *
669 671
 	 */
670 672
 	if (credit_data->number_of_calls == 0) {
671 673
 		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);
... ...
@@ -882,9 +891,29 @@ exit:
882 882
 }
883 883
 
884 884
 // must be called with lock held on credit_data
885
+/* terminate all calls and remove credit_data */
885 886
 void terminate_all_calls(credit_data_t *credit_data) {
886 887
 	call_t *call = NULL,
887 888
            *tmp = NULL;
889
+	struct str_hash_entry *cd_entry = NULL;
890
+	hash_tables_t *hts      = NULL;
891
+
892
+	switch(credit_data->type) {
893
+        case CREDIT_MONEY:
894
+            hts =  &_data.money;
895
+            break;
896
+        case CREDIT_TIME:
897
+            hts =  &_data.time;
898
+            break;
899
+        case CREDIT_CHANNEL:
900
+            hts =  &_data.channel;
901
+            break;
902
+        default:
903
+            LM_ERR("BUG: Something went terribly wrong\n");
904
+            return;
905
+    }
906
+    
907
+	cd_entry = str_hash_get(hts->credit_data_by_client, credit_data->call_list->client_id.s, credit_data->call_list->client_id.len);
888 908
 
889 909
 	credit_data->deallocating = 1;
890 910
 
... ...
@@ -902,6 +931,36 @@ void terminate_all_calls(credit_data_t *credit_data) {
902 902
 			LM_WARN("invalid call structure %p\n", call);
903 903
 		}
904 904
 	}
905
+
906
+	cnxcc_lock(hts->lock);
907
+
908
+	if (_data.redis) {                                                                                                                                                               
909
+		redis_clean_up_if_last(credit_data);
910
+		shm_free(credit_data->str_id);
911
+	}
912
+    
913
+	/*
914
+     * Remove the credit_data_t from the hash table
915
+	 */
916
+	str_hash_del(cd_entry);
917
+    
918
+	cnxcc_unlock(hts->lock);
919
+    
920
+	/*
921
+	 * Free client_id in list's root
922
+	 */
923
+	shm_free(credit_data->call_list->client_id.s);
924
+	shm_free(credit_data->call_list);
925
+    
926
+	/*
927
+	 * Release the lock since we are going to free the entry down below
928
+	 */
929
+	cnxcc_unlock(credit_data->lock);
930
+    
931
+	/*
932
+	 * Free the whole entry
933
+	 */
934
+	__free_credit_data_hash_entry(cd_entry);
905 935
 }
906 936
 
907 937
 /*
... ...
@@ -1099,6 +1158,11 @@ no_memory:
1099 1099
 static credit_data_t *__alloc_new_credit_data(str *client_id, credit_type_t type) {
1100 1100
 	credit_data_t *credit_data = shm_malloc(sizeof(credit_data_t));;
1101 1101
 
1102
+	if (credit_data == NULL)
1103
+		goto no_memory;
1104
+	
1105
+	memset(credit_data, 0, sizeof(credit_data_t));
1106
+
1102 1107
 	cnxcc_lock_init(credit_data->lock);
1103 1108
 
1104 1109
 	credit_data->call_list = shm_malloc(sizeof(call_t));