void cc_queue_rmv_call( struct cc_data *data, struct cc_call *call) { LM_DBG(" QUEUE - removing call %p \n",call); if ( !is_call_in_queue(data, call) ) { LM_CRIT(" QUEUE - call not in queue l=%p, h=%p\n", call->lower_in_queue, call->higher_in_queue); abort(); } if (call->lower_in_queue) { call->lower_in_queue->higher_in_queue = call->higher_in_queue; } else { data->queue.last = call->higher_in_queue; } if (call->higher_in_queue) { call->higher_in_queue->lower_in_queue = call->lower_in_queue; } else { data->queue.first = call->lower_in_queue; } call->lower_in_queue = call->higher_in_queue = NULL; data->queue.calls_no--; update_stat( call->flow->st_queued_calls, -1 ); }
void cc_queue_push_call(struct cc_data *data, struct cc_call *call, int top) { struct cc_call *call_it; int n = 0; LM_DBG(" QUEUE - adding call %p \n",call); if ( is_call_in_queue(data, call) ) { LM_CRIT(" QUEUE - call already in queue \n"); abort(); } if (top) { /* add the call in the very top of the queue */ call_it = NULL; } else { /* search (priority based) the place in queue */ for(call_it=data->queue.last ; call_it ; call_it=call_it->higher_in_queue){ if (call_it->flow->priority <= call->flow->priority) break; n++; } } if (call_it) { /* add before it */ if (call_it->lower_in_queue) { call_it->lower_in_queue->higher_in_queue = call; } else { data->queue.last = call; } call->lower_in_queue = call_it->lower_in_queue; call->higher_in_queue = call_it; call_it->lower_in_queue = call; } else { /* add in top of the queue */ call->lower_in_queue = data->queue.first; if (data->queue.first) { data->queue.first->higher_in_queue = call; } else { data->queue.last = call; } call->higher_in_queue = NULL; data->queue.first = call; } data->queue.calls_no++; update_stat( call->flow->st_queued_calls, +1 ); LM_DBG("adding call on pos %d (already %d calls), l=%p h=%p\n", n, data->queue.calls_no, call->lower_in_queue, call->higher_in_queue); call->ref_cnt++; if (call->queue_start==0) call->queue_start = get_ticks(); }
static void terminate_call(struct cc_call *call, b2bl_dlg_stat_t* stat, call_state prev_state) { str un, fid, aid; int type; if(prev_state == CC_CALL_ENDED) { LM_CRIT("BUG - terminate state \n"); return; } LM_DBG("terminating call %p (stat=%p)\n",call,stat); lock_get( data->lock ); prepare_cdr( call, &un, &fid , &aid); if (prev_state==CC_CALL_TOAGENT) { /* free the agent */ if (stat && stat->call_time && prev_state==CC_CALL_TOAGENT) { call->agent->state = CC_AGENT_WRAPUP; call->agent->last_call_end = get_ticks(); call->flow->processed_calls ++; call->flow->avg_call_duration = ( ((float)stat->call_time + ((float)call->flow->avg_call_duration * (call->flow->processed_calls-1)) ) ) / call->flow->processed_calls ; /* update awt for established calls */ update_awt( stat->start_time - call->recv_time ); update_cc_flow_awt(call->flow, stat->start_time - call->recv_time); update_cc_agent_att(call->agent, stat->call_time); } else { call->agent->state = CC_AGENT_FREE; /* update awt for failed calls */ update_awt( get_ticks() - call->recv_time ); update_cc_flow_awt( call->flow, get_ticks() - call->recv_time ); } /* update last_call_end for agent */ cc_db_update_agent_end_call(call->agent); call->agent->ref_cnt--; call->agent = NULL; } else { /* update awt for failed calls */ update_awt( get_ticks() - call->recv_time ); update_cc_flow_awt( call->flow, get_ticks() - call->recv_time ); } /* remove the call from queue (if there) */ if ( is_call_in_queue(data, call) ) { cc_queue_rmv_call( data, call); call->ref_cnt--; } call->flow->ongoing_calls--; lock_release( data->lock ); if (call->setup_time==-1 && stat) call->setup_time = stat->setup_time; /* generate CDR */ type = (stat==NULL) ? -1 : ((prev_state==CC_CALL_TOAGENT && stat->call_time)? 0 : 1); cc_write_cdr( &un, &fid, &aid, type, call->recv_time, ((type==0)? stat->start_time : get_ticks()) - call->recv_time , (type==0)?stat->call_time:0 , call->setup_time, call->no_rejections, call->fst_flags, call->id); cc_db_delete_call(call); }