352 lines
7.0 KiB
C++
352 lines
7.0 KiB
C++
|
#include <errno.h>
|
|||
|
|
|||
|
#include "agent_client.h"
|
|||
|
|
|||
|
#include "stat_index.h"
|
|||
|
#include "agent_client_unit.h"
|
|||
|
#include "agent_receiver.h"
|
|||
|
#include "agent_sender.h"
|
|||
|
#include "log.h"
|
|||
|
#include "poll_thread.h"
|
|||
|
#include "agent_multi_request.h"
|
|||
|
#include "packet.h"
|
|||
|
#include "task_request.h"
|
|||
|
#include "agent_multi_request.h"
|
|||
|
|
|||
|
//static CStatItemU32 statTaskClientTimeout;
|
|||
|
static CStatItemU32 statAgentAcceptCount;
|
|||
|
static CStatItemU32 statAgentCurConnCount;
|
|||
|
static CStatItemU32 statAgentExpireCount;
|
|||
|
static CStatItemU32 statTaskClientTimeout;
|
|||
|
|
|||
|
CAgentResultQueue::~CAgentResultQueue()
|
|||
|
{
|
|||
|
CPacket * p;
|
|||
|
|
|||
|
while(NULL != (p = packet.Pop()))
|
|||
|
{
|
|||
|
p->FreeResultBuff();
|
|||
|
delete p;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
class CAgentReply : public CReplyDispatcher<CTaskRequest>
|
|||
|
{
|
|||
|
public:
|
|||
|
CAgentReply() {
|
|||
|
statInitFlag = false;
|
|||
|
}
|
|||
|
virtual ~CAgentReply() {}
|
|||
|
virtual void ReplyNotify(CTaskRequest *task);
|
|||
|
private:
|
|||
|
bool statInitFlag;
|
|||
|
};
|
|||
|
|
|||
|
void CAgentReply::ReplyNotify(CTaskRequest *task)
|
|||
|
{
|
|||
|
log_debug("CAgentReply::ReplyNotify start");
|
|||
|
|
|||
|
CClientAgent * client = task->OwnerClient();
|
|||
|
if(client == NULL)
|
|||
|
{
|
|||
|
/* client gone, finish this task */
|
|||
|
task->DoneOneAgentSubRequest();
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
client->RecordRequestProcessTime(task);
|
|||
|
|
|||
|
int client_timeout = 6000;
|
|||
|
int req_delaytime = task->responseTimer.live();
|
|||
|
|
|||
|
if (!statInitFlag) {
|
|||
|
statAgentExpireCount = statmgr.GetItemU32(INCOMING_EXPIRE_REQ);
|
|||
|
statTaskClientTimeout = statmgr.GetItemU32(TASK_CLIENT_TIMEOUT);
|
|||
|
statInitFlag = true;
|
|||
|
}
|
|||
|
|
|||
|
statTaskClientTimeout = client_timeout;
|
|||
|
log_debug("task client_timeout: %d", client_timeout);
|
|||
|
|
|||
|
if ( (req_delaytime / 1000 ) >= client_timeout) //ms
|
|||
|
{
|
|||
|
log_debug("CAgentReply::ReplyNotify client_timeout[%d]ms, req delay time[%d]us", 6000, req_delaytime);
|
|||
|
//task->DoneOneAgentSubRequest();
|
|||
|
statAgentExpireCount++;
|
|||
|
//return;
|
|||
|
}
|
|||
|
CPacket * packet = new CPacket();
|
|||
|
if(packet == NULL)
|
|||
|
{
|
|||
|
/* make response error, finish this task */
|
|||
|
task->DoneOneAgentSubRequest();
|
|||
|
log_crit("no mem new CPacket");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
packet->EncodeResult(task);
|
|||
|
task->DoneOneAgentSubRequest();
|
|||
|
|
|||
|
client->AddPacket(packet);
|
|||
|
if(client->SendResult() < 0)
|
|||
|
{
|
|||
|
log_error("cliengAgent SendResult error");
|
|||
|
delete client;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
log_debug("CAgentReply::ReplyNotify stop");
|
|||
|
}
|
|||
|
|
|||
|
static CAgentReply agentReply;
|
|||
|
|
|||
|
/* sender and receiver should inited ok */
|
|||
|
CClientAgent::CClientAgent(CPollThread * o, CAgentClientUnit * u, int fd):
|
|||
|
CPollerObject(o, fd),
|
|||
|
ownerThread(o),
|
|||
|
owner(u),
|
|||
|
tlist(NULL)
|
|||
|
{
|
|||
|
tlist = u->TimerList();
|
|||
|
sender = new CAgentSender(fd);
|
|||
|
if(NULL == sender)
|
|||
|
{
|
|||
|
log_error("no mem to new sender");
|
|||
|
throw (int)-ENOMEM;
|
|||
|
}
|
|||
|
|
|||
|
if(sender && sender->Init() < 0)
|
|||
|
{
|
|||
|
delete sender;
|
|||
|
sender = NULL;
|
|||
|
log_error("no mem to init sender");
|
|||
|
throw (int)-ENOMEM;
|
|||
|
}
|
|||
|
|
|||
|
if(sender)
|
|||
|
{
|
|||
|
receiver = new CAgentReceiver(fd);
|
|||
|
if(NULL == receiver)
|
|||
|
{
|
|||
|
log_error("no mem to new receiver");
|
|||
|
throw (int)-ENOMEM;
|
|||
|
}
|
|||
|
|
|||
|
if(receiver && receiver->Init() < 0)
|
|||
|
{
|
|||
|
log_error("no mem to init receiver");
|
|||
|
throw (int)-ENOMEM;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
statAgentAcceptCount = statmgr.GetItemU32(AGENT_ACCEPT_COUNT);
|
|||
|
statAgentCurConnCount = statmgr.GetItemU32(AGENT_CONN_COUNT);
|
|||
|
|
|||
|
statAgentAcceptCount++;
|
|||
|
statAgentCurConnCount++;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
CClientAgent::~CClientAgent()
|
|||
|
{
|
|||
|
log_debug("~CClientAgent start");
|
|||
|
CListObject<CAgentMultiRequest> * node = rememberReqHeader.ListNext();
|
|||
|
CAgentMultiRequest * req;
|
|||
|
|
|||
|
/* notify all request of this client I'm gone */
|
|||
|
while(node != &rememberReqHeader)
|
|||
|
{
|
|||
|
req = node->ListOwner();
|
|||
|
req->ClearOwnerInfo();
|
|||
|
req->DetachFromOwnerClient();
|
|||
|
node = rememberReqHeader.ListNext();
|
|||
|
}
|
|||
|
|
|||
|
if(receiver)
|
|||
|
delete receiver;
|
|||
|
if(sender)
|
|||
|
delete sender;
|
|||
|
|
|||
|
DetachPoller();
|
|||
|
|
|||
|
log_debug("~CClientAgent end");
|
|||
|
}
|
|||
|
|
|||
|
int CClientAgent::AttachThread()
|
|||
|
{
|
|||
|
DisableOutput();
|
|||
|
EnableInput();
|
|||
|
|
|||
|
if(AttachPoller() < 0)
|
|||
|
{
|
|||
|
log_error("client agent attach agengInc thread failed");
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
/* no idle test */
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
void CClientAgent::RememberRequest(CTaskRequest * request)
|
|||
|
{
|
|||
|
request->LinkToOwnerClient(rememberReqHeader);
|
|||
|
}
|
|||
|
|
|||
|
CTaskRequest * CClientAgent::PrepareRequest(char * recvbuff, int recvlen, int pktcnt)
|
|||
|
{
|
|||
|
CTaskRequest * request;
|
|||
|
|
|||
|
request = new CTaskRequest();
|
|||
|
if(NULL == request)
|
|||
|
{
|
|||
|
free(recvbuff);
|
|||
|
log_crit("no mem allocate for new agent request");
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
request->SetOwnerInfo(this, 0, NULL);
|
|||
|
request->SetOwnerClient(this);
|
|||
|
request->PushReplyDispatcher(&agentReply);
|
|||
|
request->SaveRecvedResult(recvbuff, recvlen, pktcnt);
|
|||
|
|
|||
|
/* assume only a few sub request decode error */
|
|||
|
if(request->DecodeAgentRequest() < 0)
|
|||
|
{
|
|||
|
delete request;
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
/* no mem new task case */
|
|||
|
if(request->IsAgentRequestCompleted())
|
|||
|
{
|
|||
|
delete request;
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
RememberRequest(request);
|
|||
|
|
|||
|
return request;
|
|||
|
}
|
|||
|
|
|||
|
int CClientAgent::RecvRequest()
|
|||
|
{
|
|||
|
RecvedPacket packets;
|
|||
|
char * recvbuff = NULL;
|
|||
|
int recvlen = 0;
|
|||
|
int pktcnt = 0;
|
|||
|
CTaskRequest * request = NULL;
|
|||
|
|
|||
|
packets = receiver->Recv();
|
|||
|
|
|||
|
if(packets.err < 0)
|
|||
|
return -1;
|
|||
|
else if(packets.pktCnt == 0)
|
|||
|
return 0;
|
|||
|
|
|||
|
recvbuff = packets.buff;
|
|||
|
recvlen = packets.len;
|
|||
|
pktcnt = packets.pktCnt;
|
|||
|
|
|||
|
request = PrepareRequest(recvbuff, recvlen, pktcnt);
|
|||
|
if(request != NULL)
|
|||
|
owner->TaskNotify(request);
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
/* exit when recv error*/
|
|||
|
void CClientAgent::InputNotify()
|
|||
|
{
|
|||
|
log_debug("CClientAgent::InputNotify() start");
|
|||
|
if(RecvRequest() < 0)
|
|||
|
{
|
|||
|
log_debug("erro when recv");
|
|||
|
delete this;
|
|||
|
return;
|
|||
|
}
|
|||
|
DelayApplyEvents();
|
|||
|
log_debug("CClientAgent::InputNotify() stop");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
return error if sender broken
|
|||
|
*/
|
|||
|
int CClientAgent::SendResult()
|
|||
|
{
|
|||
|
if(sender->IsBroken())
|
|||
|
{
|
|||
|
log_error("sender broken");
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
while(1)
|
|||
|
{
|
|||
|
|
|||
|
CPacket* frontPkt = resQueue.Front();
|
|||
|
if (NULL == frontPkt)
|
|||
|
{
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (frontPkt->VecCount() + sender->VecCount() > SENDER_MAX_VEC)
|
|||
|
{
|
|||
|
/*<2A><><EFBFBD><EFBFBD>ط<EFBFBD><D8B7><EFBFBD>ӡerror<6F><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>10s<30>ڻ<EFBFBD>5<EFBFBD><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˴η<CBB4>֧<EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD>ͳ<EFBFBD><CDB3><EFBFBD>ӽ<EFBFBD>̻<EFBFBD><CCBB>ϱ<EFBFBD><CFB1>澯*/
|
|||
|
log_error("the sum value of front packet veccount[%d] and sender veccount[%d]is greater than SENDER_MAX_VEC[%d]",
|
|||
|
frontPkt->VecCount(), sender->VecCount(), SENDER_MAX_VEC);
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
CPacket * pkt ;
|
|||
|
pkt = resQueue.Pop();
|
|||
|
if(NULL == pkt)
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
if(sender->AddPacket(pkt) < 0)
|
|||
|
{
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if(sender->Send() < 0)
|
|||
|
{
|
|||
|
log_error("agent client send error");
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
if(sender->LeftLen() != 0)
|
|||
|
EnableOutput();
|
|||
|
else
|
|||
|
DisableOutput();
|
|||
|
|
|||
|
DelayApplyEvents();
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
void CClientAgent::OutputNotify()
|
|||
|
{
|
|||
|
log_debug("CClientAgent::OutputNotify() start");
|
|||
|
if(SendResult() < 0)
|
|||
|
{
|
|||
|
log_debug("error when response");
|
|||
|
delete this;
|
|||
|
return;
|
|||
|
}
|
|||
|
log_debug("CClientAgent::OutputNotify() stop");
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
void CClientAgent::RecordRequestProcessTime(CTaskRequest * task)
|
|||
|
{
|
|||
|
owner->RecordRequestTime(task);
|
|||
|
}
|