www.pudn.com > acdx.rar > CallBacklog.cpp


 /*============================================================= 
 
  
 Function: 
		This class stores calls that could not be routed, yet. 
 
 
 Author: Leon Wang  
==============================================================*/ 
// CallBacklog.cpp: implementation of the CCallBacklog class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "CallBacklog.h" 
#include "Acdconfig.h" 
#include "acdx.h" 
#include "socket/Lock.h" 
 
extern Lock g_lock_pend;  // use global lock parameter 
 
//Lock g_lock_pend("pendlist"); 
 
#pragma warning(disable: 4786) 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
class ACDConfig; 
class ACDX; 
class Agent; 
 
//##ModelId=424BB6460279 
CCallBacklog::CCallBacklog() 
{ 
	//pendingList.reserve(10); 
 
} 
//##ModelId=424BB646027A 
CCallBacklog::CCallBacklog(GkClient* _gkclient) 
{ 
     gkclient = _gkclient; 
     config = ACDConfig::getInstance();	 
	 //pendingList.reserve(10); 
} 
//##ModelId=424BB6460288 
CCallBacklog::~CCallBacklog() 
{ 
 
} 
 
   /** 
     * Sore a new pending request if there is still rome in the queue, otherwise reject it. 
     * @param queue         called queue 
     * @param callerEndId   caller endpoint ID 
     * @param callRef       callRef 
     * @param callerAlias   caller H.323 alias 
     * @param callerIp      caller IP 
     * @param status        PendingRequest.RINGING / TALKING 
     */ 
//synchronized 
//##ModelId=424BB646028A 
void CCallBacklog::store(CString queue,  
						   CString callerEndId,  
						   CString callRef,  
						   CString callerAlias,  
						   CString callerIp,  
						   int status)  
{ 
 
		if (!g_lock_pend.lock()) { 
			return; 
		} 
	 
	   int maxSize = config->getMaxSize(queue);// this is queue size it in ini queuename_size=x 
       if ((maxSize <= 0) || (pendingList.size() < maxSize)) { 
           int priority = config->getPriority(queue); 
		   //SYSTEMTIME systime; 
		   //GetSystemTime(&systime); 
		    
           //long timeout = systime.wMilliseconds; 
		   long timeout = GetTickCount(); 
 
           if (status == PendingRequest::TALKING) 
               timeout += (config->getTalkTimeout(queue) * 1000); 
           else 
               timeout += (config->getRingTimeout(queue) * 1000); 
 
           PendingRequest* request = new PendingRequest(priority, queue, callerEndId, callRef, callerAlias, callerIp, timeout, status); 
		   Logger::log("Call from " + callerAlias + " to " + queue + " queued."); 
		   pendingList.reserve(10); 
		   pendingList.push_back(*request); // add this pendrequest in list 
 
       } else { 
		   Logger::log("Queue for " + queue + " is full - rejecting call."); 
           gkclient->routeReject(callerEndId, callRef); 
        } 
	    g_lock_pend.unlock(); 
} 
 
 
    /** 
     * Check if requests have expired and delete + reject them. 
     */ 
//synchronized  
//##ModelId=424BB64602A7 
void CCallBacklog::expire()  
{ 
 
		if (!g_lock_pend.lock()) { 
			return; 
		} 
	 
	   //SYSTEMTIME systime; 
	   //GetSystemTime(&systime); 
       //long now = systime.wMilliseconds; 
		long now = GetTickCount(); 
	   std::vector::iterator pendElement; 
	    
	   for(pendElement=pendingList.begin();pendElement!=pendingList.end();++pendElement) 
	   { 
		   if(pendingList.empty()) break; 
			PendingRequest r = (PendingRequest) *pendElement; 
			if (r.timeoutdisconnectAlias(r.callerAlias); 
					} 
				}else if ( (config->getQueueingMode(r.queue) == ACDConfig::QUEUEING_MODE_RINGANDTALK) &&    // transfer if: queue mode is talk after ring 
					(r.status == PendingRequest::RINGING) && 
					( ((wqName = ACDX::getInstance()->getWaitQueue(r.queue)) != "") ) )  
				{             // AND we have a talinmg queue available 
				 
					Logger::debug("*---callback expire-waiting queue name "+wqName);//test wqueue name 
					Logger::log("Pending call from " + r.callerAlias + " to " + r.queue + " routed to WQ " + wqName + " after ring timeout."); 
                    gkclient->routeToAlias(wqName, r.callerEndId, r.callRef); 
                    r.status = PendingRequest::TALKING; 
					//SYSTEMTIME systime2; 
					//GetSystemTime(&systime2); 
 
                    //r.timeout =  systime2.wMilliseconds + (config->getTalkTimeout(r.queue) * 1000); 
					r.timeout =  GetTickCount() + (config->getTalkTimeout(r.queue) * 1000); 
 
				}else 
				{ 
 
					Logger::log("Pending call from " + r.callerAlias + " to " + r.queue + " expired."); 
					if(!pendingList.empty()) 
					{ 
						pendElement = pendingList.erase(pendElement); // remove iterator; 
						gkclient->routeReject(r.callerEndId, r.callRef); 
					} 
 
				} 
				 
			} 
			 
	   }	 
 	g_lock_pend.unlock(); 
} 
 
 
   /** 
     * Check if we have a pending call this agent could handle. 
     * @param agent available Agent 
     */ 
//synchronized  
//##ModelId=424BB64602A8 
void CCallBacklog::checkPending(Agent* agent,aList & _aliasList)  
{ 
 
		if (!g_lock_pend.lock()) { 
			return; 
		} 
	 
	std::vector::iterator pendElement; 
	PendingRequest r; 
	for(pendElement=pendingList.begin();pendElement!=pendingList.end();++pendElement) 
	{ 
		if (pendingList.empty()) { 
			break; 
		} 
		r = (PendingRequest) *pendElement; 
		if (agent->isAvailable(r.queue)) { 
               CString alias = agent->getAlias();//((Alias*)agent)->getAlias(); 
			   Logger::log("Pending call from " + r.callerAlias + " to " + r.queue + " routed to " + alias); 
			   if (!pendingList.empty())  
			   { 
				   	pendElement = pendingList.erase(pendElement); // remove iterator; 
			    
			 
			   //	 need set aliaslist -- add code 
 
				   std::list::iterator aliasElement; 
				   Agent _agent; 
				   for(aliasElement = _aliasList.begin();aliasElement != _aliasList.end();aliasElement++ ) 
				   { 
					   _agent = *aliasElement; 
					   if (_agent.getAlias()==alias) { 
						   aliasElement->setState(Alias::TALKING); 
						   aliasElement->setLastCall(); 
					   }//if 
				   }//for 
				   if (r.status == PendingRequest::RINGING) 
					   gkclient->routeToAlias(alias, r.callerEndId, r.callRef);// routecall in gk 
				   else 
					   gkclient->transferCall(r.callerAlias, alias);//  transfercall in gk 
				   return; 
				} 
		} 
	} 
 	g_lock_pend.unlock(); 
} 
 
    /** 
     * Remove all pending requests for this endpoint ID. 
     * @param epid  endpoint ID 
     */ 
//    public synchronized  
//##ModelId=424BB64602AB 
void CCallBacklog::removeAllRequests(CString epid)  
{ 
 
		if (!g_lock_pend.lock()) { 
			return; 
		} 
	 
	std::vector::iterator pendElement; 
	for(pendElement=pendingList.begin();pendElement!=pendingList.end();pendElement++) 
	{ 
		if (pendingList.empty()) { 
			break; 
		} 
		PendingRequest r = (PendingRequest) *pendElement; 
		if (epid==r.callerEndId)  
		{ 
			pendElement = pendingList.erase(pendElement); // remove iterator; 
		} 
		if (pendingList.empty()) { 
			break; 
		} 
	} 
 	g_lock_pend.unlock(); 
} 
 
    /** 
     * Dump the list of all pending requests for debug. 
     * @return  formatted list 
     */ 
// synchronized		 
//##ModelId=424BB64602B8 
CString CCallBacklog::dumpPendingList()  
{ 
 
		if (!g_lock_pend.lock()) { 
			return ""; 
		} 
	 
	//pendingList. 
	if (pendingList.empty()) { 
		return "no caller in pending list!"; 
	} 
	int pendlistNumber = pendingList.size(); 
	char ch[4]; 
	itoa(pendlistNumber,ch,10); 
 
    CString result = "Pending list (" + CString(ch) + " entries)\n"; 
 
	std::vector::iterator pendElement; 
	for(pendElement=pendingList.begin();pendElement!=pendingList.end();++pendElement) 
	{ 
		PendingRequest r = (PendingRequest) *pendElement; 
	    char pri_ch[4]; 	 
		itoa(r.priority,pri_ch,10); // pri int number 
 
		result = result + r.queue + " (priority level: " + CString(pri_ch) + ") " + r.callerAlias + " (" + r.callerEndId + "/" +r.callRef + ")\n"; 
	} 
    return result; 
 	g_lock_pend.unlock(); 
}