MT#57118 Rework the call's deconstruction logic

This commit: 6f0ad0db0f
introduced an improved behavior of the call deconstruction
when dealing with multiple forked legs. But it also
introduced a regression related to TPCC related calls.

This is because it takes into consideration existing
`->viabranches`, which is not efficient in certain cases.

Instead, we just have to ensure, whether there are
other monologues of the call object, which are not directly
"visible" for this branch being cancelled (so they are not directly
associated to that), but they might have own associations
present, which means the call mustn't be globally destoroyed.

Change-Id: I630f2d88ef3b557af3a95816fc2703daccaff374
pull/1657/head
Donat Zenichev 3 years ago
parent 177b4111c2
commit 0994ffbe75

@ -4276,7 +4276,9 @@ static unsigned int monologue_delete_iter(struct call_monologue *a, int delete_d
if (!call)
return 0;
unsigned int call_viabranches_count = g_hash_table_size(call->viabranches);
unsigned int ml_associated_count = g_hash_table_size(a->associated_tags);
unsigned int call_monologues_count = g_queue_get_length(&call->monologues);
GList *associated = g_hash_table_get_values(a->associated_tags);
unsigned int ret = 0;
@ -4295,22 +4297,42 @@ static unsigned int monologue_delete_iter(struct call_monologue *a, int delete_d
ret |= 0x2;
}
// look at all associated tags: cascade deletion to those which have no other associations left
for (GList *l = associated; l; l = l->next) {
/* first, look at all associated tags: cascade deletion to those which have
* no other associations left */
for (GList *l = associated; l; l = l->next)
{
struct call_monologue *b = l->data;
__tags_unassociate(a, b);
if (g_hash_table_size(b->associated_tags) == 0)
ret |= monologue_delete_iter(b, delete_delay);
ret |= monologue_delete_iter(b, delete_delay); /* schedule deletion of B */
else
ret |= 0x1;
}
/* Take into account an amount of forked legs we have now.
* If there's more than 1 forked leg, don't mark the call for a full destruction,
* since other forks might be successful. Only destroy this branch and associated to it monologue(s).
*/
if (call_viabranches_count > 1)
ret |= 0x1;
/* now, if one call object contains some other monologues, which can have own associations,
* not direclty visible for this very monologue,
* then ensure, whether we can afford to destroy the whole call now.
* Maybe some of them still needs a media to flow. */
if (ml_associated_count < call_monologues_count && !(ret & 0x1)) {
for (GList * l = call->monologues.head; l; l = l->next)
{
struct call_monologue * ml = l->data;
/* skip those already checked */
if (g_hash_table_lookup(a->associated_tags, ml))
continue;
/* we are not clearing here monologues not associated with us,
* only checking, if we can afford whole call destroy.
*/
if (g_hash_table_size(ml->associated_tags) > 0) {
ret |= 0x1;
break;
}
}
}
/* otherwise, we have only one call leg, so association monologue A to monologue B (no other branches)
* and we can simple destroy the whole call */
g_list_free(associated);
return ret;

Loading…
Cancel
Save