void acd_agent::SetStatus(const acd::AgentStatusT& agentStatus, const acd::CallEventReasonT& reason, const string& restReason) { time_t lastStatusTime = m_currStatusTime; acd::AgentStatusT lastAgentStatus = m_agentStatus; m_currStatusTime = time(NULL); m_agentStatus = agentStatus; switch (lastAgentStatus.get_value()) { case acd::AgentStatusT::AsReadyState: m_freeTotalTime += m_currStatusTime - lastStatusTime; break; case acd::AgentStatusT::AsBusyState: m_busyTotalTime += m_currStatusTime - lastStatusTime; break; case acd::AgentStatusT::AsRestState: m_restTotalTime += m_currStatusTime - lastStatusTime; break; default: break; } SendEventT* p_agentEvent = new SendEventT; p_agentEvent->m_event_id = acd_tool::CreatEventId(); p_agentEvent->m_callback_proxy = m_callback_ptr; p_agentEvent->m_event_type = AGENT_EVENT; p_agentEvent->m_agent_event.agentId = m_agentId; p_agentEvent->m_agent_event.eventId = acd::CallEventTypeT::CeUnKnownEvent; p_agentEvent->m_agent_event.agentDn = m_agentDn; p_agentEvent->m_agent_event.callId = ""; p_agentEvent->m_agent_event.sessionId = 0; p_agentEvent->m_agent_event.agentStatus = m_agentStatus; p_agentEvent->m_agent_event.originalCallid = ""; p_agentEvent->m_agent_event.partyNum = 0; p_agentEvent->m_agent_event.otherParty = ""; p_agentEvent->m_agent_event.otherAttr = acd::PartyAttributeT::PaUnknown; p_agentEvent->m_agent_event.originatingParty = ""; p_agentEvent->m_agent_event.originalAni = ""; p_agentEvent->m_agent_event.originalDnis = ""; p_agentEvent->m_agent_event.reason = reason; p_agentEvent->m_agent_event.timestamp = bgcc::TimeUtil::get_timestamp_us(); WriteTraceLog(restReason); acd_tool::m_send_event_manager.send_event(p_agentEvent, m_handle); }
void acd_agent::ProcessIMSEvent(const ims::CallEventT& event) { SingleRWLocker s(&m_RWLock, true); m_sessionId = event.sessionid; m_callId = event.callid; time_t lastStatusTime = m_currStatusTime; acd::AgentStatusT lastAgentStatus = m_agentStatus; m_currStatusTime = time(NULL); switch (lastAgentStatus.get_value()) { case acd::AgentStatusT::AsReadyState: m_freeTotalTime += m_currStatusTime - lastStatusTime; break; case acd::AgentStatusT::AsBusyState: m_busyTotalTime += m_currStatusTime - lastStatusTime; break; case acd::AgentStatusT::AsRestState: m_restTotalTime += m_currStatusTime - lastStatusTime; break; default: break; } SendEventT* p_agentEvent = new SendEventT; p_agentEvent->m_event_id = acd_tool::CreatEventId(); p_agentEvent->m_callback_proxy = m_callback_ptr; p_agentEvent->m_event_type = AGENT_EVENT; p_agentEvent->m_agent_event.agentId = m_agentId; p_agentEvent->m_agent_event.eventId = acd_tool::TranslateCallEvent(event.eventType); p_agentEvent->m_agent_event.agentDn = event.device; p_agentEvent->m_agent_event.callId = event.callid; p_agentEvent->m_agent_event.sessionId = event.sessionid; //p_agentEvent->m_agent_event.agentStatus = m_agentStatus; p_agentEvent->m_agent_event.originalCallid = event.originalCallid; p_agentEvent->m_agent_event.partyNum = event.partyNum; p_agentEvent->m_agent_event.otherParty = event.otherDevice; p_agentEvent->m_agent_event.otherAttr = acd_tool::TranslatePartyAtt(event.otherAttr); p_agentEvent->m_agent_event.originatingParty = event.originatingParty; p_agentEvent->m_agent_event.originalAni = event.originalAni; p_agentEvent->m_agent_event.originalDnis = event.originalDnis; //p_agentEvent->m_agent_event.reason = reason; p_agentEvent->m_agent_event.timestamp = bgcc::TimeUtil::get_timestamp_us(); acd::CallEventReasonT reason = acd_tool::TranslateCallReason(event.reason); switch (event.state.get_value()) { case ims::CallStateT::SG_UnknownState: m_agentStatus = acd::AgentStatusT::AsUnknownState; break; case ims::CallStateT::SG_IdleState: { if (lastAgentStatus == acd::AgentStatusT::AsAlertingState || lastAgentStatus == acd::AgentStatusT::AsHalfAlertingState || lastAgentStatus == acd::AgentStatusT::AsConnectingState || lastAgentStatus == acd::AgentStatusT::AsHalfConnectedState || lastAgentStatus == acd::AgentStatusT::AsConsultConnectingState) { // 振铃中挂断 if (event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnected_InternalCall || event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnected_NormalCall || event.eventType == ims::CallEventTypeT::SG_ThisPartyTransferred_NormalCall || event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnected_ConsultCall || event.eventType == ims::CallEventTypeT::SG_ThisPartyTransferred_ConsultCall || event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnect_ConferenceCall || event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnect_MonitorCall || event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnect_IntrudeCall) { // 本方挂断 reason = acd::CallEventReasonT::CerIdleErrorSelfHangup; m_callinfo.SetReleaseCause(ReleaseCauseT::THISPARTY); } else { reason = acd::CallEventReasonT::CerIdleErrorOtherHangup; m_callinfo.SetReleaseCause(ReleaseCauseT::OTHERPARTY); } if (0 < m_callTime) { m_callTotalTime += m_currStatusTime - m_callTime; } if (0 < m_answerTime) { m_answerTotalTime += m_currStatusTime - m_answerTime; } m_callinfo.SetAniDnis(event.originalAni, event.originalDnis); if (lastAgentStatus == acd::AgentStatusT::AsConnectingState) { m_callinfo.SetConnectEnd(m_currStatusTime); m_callinfo.SetCallEnd(m_currStatusTime); } else if (lastAgentStatus == acd::AgentStatusT::AsConsultConnectingState) { m_callinfo.SetCallEnd(m_currStatusTime); } else { m_callinfo.SetAckEnd(m_currStatusTime); m_callinfo.SetCallEnd(m_currStatusTime); } if (m_callinfo.isValid()) { // 如果话单没有起始信息,则不必要写 m_callinfo.WriteCallLog(); m_callinfo.reset(); } Reset(); } else if (lastAgentStatus == acd::AgentStatusT::AsConnectedState || lastAgentStatus == acd::AgentStatusT::AsInternalConnectedState || lastAgentStatus == acd::AgentStatusT::AsSuspendedState || lastAgentStatus == acd::AgentStatusT::AsConsultConnectedState || lastAgentStatus == acd::AgentStatusT::AsConferenceState || lastAgentStatus == acd::AgentStatusT::AsMonitorState || lastAgentStatus == acd::AgentStatusT::AsInsertState || lastAgentStatus == acd::AgentStatusT::AsMonitoredState || lastAgentStatus == acd::AgentStatusT::AsInsertedState) { // 通话中挂断 if (event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnected_InternalCall || event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnected_NormalCall || event.eventType == ims::CallEventTypeT::SG_ThisPartyTransferred_NormalCall || event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnected_ConsultCall || event.eventType == ims::CallEventTypeT::SG_ThisPartyTransferred_ConsultCall || event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnect_ConferenceCall || event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnect_MonitorCall || event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnect_IntrudeCall) { // 本方挂断 reason = acd::CallEventReasonT::CerIdleNormalSelfHangup; m_callinfo.SetReleaseCause(ReleaseCauseT::THISPARTY); } else { reason = acd::CallEventReasonT::CerIdleNormalOtherHangup; m_callinfo.SetReleaseCause(ReleaseCauseT::OTHERPARTY); } if (0 < m_callTime) { m_callTotalTime += m_currStatusTime - m_callTime; } if (0 < m_answerTime) { m_answerTotalTime += m_currStatusTime - m_answerTime; } m_callinfo.SetAniDnis(event.originalAni, event.originalDnis); m_callinfo.SetCallEnd(m_currStatusTime); if (m_callinfo.isValid()) { // 如果话单没有起始信息,则不必要写 m_callinfo.WriteCallLog(); m_callinfo.reset(); } Reset(); } else { reason = acd::CallEventReasonT::CerIdleIdle; } if (m_statusChangetype == acd::StatusChangeT::ScBusy) { m_agentStatus = acd::AgentStatusT::AsBusyState; } else { m_agentStatus = acd::AgentStatusT::AsReadyState; } break; } case ims::CallStateT::SG_AlertingState: { if (!m_callinfo.GetRoutecall()) { if (m_callinfo.isValid()) { // 如果话单没有结束信息,则需要写 m_callinfo.WriteCallLog(); m_callinfo.reset(); } m_callinfo.Initial(event.sessionid, event.callid, m_agentId, m_agentDn, _m_cur_skill, event.originalAni, event.originalDnis, 0, 0); } m_callinfo.SetAckBegin(m_currStatusTime); m_callinfo.SetCallType(event.otherAttr); m_callinfo.SetCallDirect(CallDirectT::INBOUND); m_origCaller = event.originalAni; m_origCallee = event.originalDnis; m_callTime = m_currStatusTime; m_callTimes++; m_agentStatus = acd::AgentStatusT::AsAlertingState; break; } case ims::CallStateT::SG_HalfAlertingState: { if (m_callinfo.isValid()) { // 如果话单没有结束信息,则需要写 m_callinfo.WriteCallLog(); m_callinfo.reset(); } m_callinfo.Initial(event.sessionid, event.callid, m_agentId, m_agentDn, _m_cur_skill, event.originalAni, event.originalDnis, 0, 0); m_callinfo.SetAckBegin(m_currStatusTime); m_callinfo.SetCallDirect(CallDirectT::OUTBOUND); m_origCaller = event.originalAni; m_origCallee = event.originalDnis; m_callTime = m_currStatusTime; m_callTimes++; m_agentStatus = acd::AgentStatusT::AsHalfAlertingState; break; } case ims::CallStateT::SG_ConnectingState: { if (event.eventType == ims::CallEventTypeT::SG_DestSeized_ConsultCall) { m_agentStatus = acd::AgentStatusT::AsConsultConnectingState; } else if (event.eventType == ims::CallEventTypeT::SG_OtherPartyDisconnected_ConsultCall) { m_agentStatus = acd::AgentStatusT::AsConnectingState; } else { m_callinfo.SetCallType(event.otherAttr); m_agentStatus = acd::AgentStatusT::AsConnectingState; m_callinfo.SetConnectBegin(m_currStatusTime); } break; } case ims::CallStateT::SG_ConnectedState: { if (event.eventType == ims::CallEventTypeT::SG_ThisPartyAnswered_InternalCall || event.eventType == ims::CallEventTypeT::SG_ThisPartyAnswered_NormalCall) { Record(); m_callinfo.SetConnectEnd(m_currStatusTime); m_callinfo.SetCallBegin(m_currStatusTime); m_callinfo.SetRecordFilename(m_recordFilename); m_answerTime = m_currStatusTime; m_answerTimes++; reason = acd::CallEventReasonT::CerTalkOtherCreat; } else if (event.eventType == ims::CallEventTypeT::SG_OtherPartyAnswered_InternalCall || event.eventType == ims::CallEventTypeT::SG_OtherPartyAnswered_NormalCall) { Record(); m_callinfo.SetConnectEnd(m_currStatusTime); m_callinfo.SetCallBegin(m_currStatusTime); m_callinfo.SetRecordFilename(m_recordFilename); m_answerTime = m_currStatusTime; m_answerTimes++; reason = acd::CallEventReasonT::CerTalkSelfCreat; } else if (event.eventType == ims::CallEventTypeT::SG_OtherPartyDisconnected_ConsultCall) { reason = acd::CallEventReasonT::CerTalkOtherRetrieve; } else { reason = acd::CallEventReasonT::CerTalkSelfRetrieve; } if (event.eventType == ims::CallEventTypeT::SG_OtherPartyAnswered_ConsultCall) { m_agentStatus = acd::AgentStatusT::AsConsultConnectedState; } else if (event.otherAttr == ims::PartyAttributeT::P_Internal) { m_agentStatus = acd::AgentStatusT::AsInternalConnectedState; } else { m_agentStatus = acd::AgentStatusT::AsConnectedState; } break; } case ims::CallStateT::SG_HalfConnectedState: m_agentStatus = acd::AgentStatusT::AsHalfConnectedState; m_callinfo.SetAckEnd(m_currStatusTime); break; case ims::CallStateT::SG_SuspendedState: m_agentStatus = acd::AgentStatusT::AsSuspendedState; break; case ims::CallStateT::SG_ConferenceState: { if (event.eventType == ims::CallEventTypeT::SG_ThisPartyConferenced_MonitorCall) { if (acd::AgentStatusT::AsHalfConnectedState == lastAgentStatus) { Record(); m_callinfo.SetConnectEnd(m_currStatusTime); m_callinfo.SetCallBegin(m_currStatusTime); m_callinfo.SetCallType(event.otherAttr); m_callinfo.SetRecordFilename(m_recordFilename); m_answerTime = m_currStatusTime; m_answerTimes++; } m_agentStatus = acd::AgentStatusT::AsMonitorState; } else if (event.eventType == ims::CallEventTypeT::SG_OtherPartyConferenced_MonitorCall) { m_agentStatus = acd::AgentStatusT::AsMonitoredState; } else if (event.eventType == ims::CallEventTypeT::SG_ThisPartyConferenced_IntrudeCall) { if (acd::AgentStatusT::AsHalfConnectedState == lastAgentStatus) { Record(); m_callinfo.SetConnectEnd(m_currStatusTime); m_callinfo.SetCallBegin(m_currStatusTime); m_callinfo.SetCallType(event.otherAttr); m_callinfo.SetRecordFilename(m_recordFilename); m_answerTime = m_currStatusTime; m_answerTimes++; } m_agentStatus = acd::AgentStatusT::AsInsertState; } else if (event.eventType == ims::CallEventTypeT::SG_OtherPartyConferenced_IntrudeCall) { m_agentStatus = acd::AgentStatusT::AsInsertedState; } else { m_agentStatus = acd::AgentStatusT::AsConferenceState; } break; } default: m_agentStatus = acd::AgentStatusT::AsUnknownState; break; } p_agentEvent->m_agent_event.agentStatus = m_agentStatus; p_agentEvent->m_agent_event.reason = reason; WriteTraceLog(); acd_tool::m_send_event_manager.send_event(p_agentEvent, m_handle); }
LONG __cdecl WriteRefTraceLogEx( IN PTRACE_LOG Log, IN LONG NewRefCount, IN CONST VOID * Context, IN CONST VOID * Context1, // optional extra context IN CONST VOID * Context2, // optional extra context IN CONST VOID * Context3 // optional extra context ) /*++ Routine Description: Writes a new "extended" entry to the specified ref count trace log. The entry written contains the updated reference count, stack backtrace leading up to the current caller and extra context information. Arguments: Log - The log to write to. NewRefCount - The updated reference count. Context - An uninterpreted context to associate with the log entry. Context1 - An uninterpreted context to associate with the log entry. Context2 - An uninterpreted context to associate with the log entry. Context3 - An uninterpreted context to associate with the log entry. NOTE Context1/2/3 are "optional" in that the caller may suppress debug display of these values by passing REF_TRACE_EMPTY_CONTEXT for each of them. Return Value: Index of entry in log. --*/ { REF_TRACE_LOG_ENTRY entry; ULONG hash; DWORD cStackFramesSkipped; // // Initialize the entry. // RtlZeroMemory( &entry, sizeof(entry) ); // // Set log entry members. // entry.NewRefCount = NewRefCount; entry.Context = Context; entry.Thread = GetCurrentThreadId(); entry.Context1 = Context1; entry.Context2 = Context2; entry.Context3 = Context3; // // Capture the stack backtrace. Normally, we skip two stack frames: // one for this routine, and one for RtlCaptureBacktrace() itself. // For non-Ex callers who come in via WriteRefTraceLog, // we skip three stack frames. // if ( entry.Context1 == REF_TRACE_EMPTY_CONTEXT && entry.Context2 == REF_TRACE_EMPTY_CONTEXT && entry.Context3 == REF_TRACE_EMPTY_CONTEXT ) { cStackFramesSkipped = 2; } else { cStackFramesSkipped = 1; } RtlCaptureStackBackTrace( cStackFramesSkipped, REF_TRACE_LOG_STACK_DEPTH, entry.Stack, &hash ); // // Write it to the log. // return WriteTraceLog( Log, &entry ); } // WriteRefTraceLogEx