/** @brief Handler的redo事件,在每次dispatch时执行。 @return -1:处理失败,会调用close(); 0:处理成功 */ int CwxMqInnerDispHandler::onRedo() { ///发送下一条binlog int iState = syncSendBinLog(m_tss); if (-1 == iState) { CWX_ERROR(("%s, from:%s:%u", m_tss->m_szBuf2K, m_strPeerHost.c_str(), m_unPeerPort)); CwxMsgBlock* msg = NULL; if (CWX_MQ_ERR_ERROR != CwxMqPoco::packSyncErr(m_tss->m_pWriter, msg, m_header.getTaskId(), CWX_MQ_ERR_ERROR, m_tss->m_szBuf2K, m_tss->m_szBuf2K)) { CWX_ERROR(("Failure to pack sync data reply, err=%s, from:%s:%u", m_tss->m_szBuf2K, m_strPeerHost.c_str(), m_unPeerPort)); return -1; } msg->send_ctrl().setMsgAttr(CwxMsgSendCtrl::CLOSE_NOTICE); if (!putMsg(msg)) { CwxMsgBlockAlloc::free(msg); CWX_ERROR(("Failure push msg to send queue. from:%s:%u", m_strPeerHost.c_str(), m_unPeerPort)); return -1; } } else if (0 == iState) { ///产生continue的消息 channel()->regRedoHander(this); } return 0; }
int UnistorHandler4Trans::open (void * arg){ m_bAuth = false; int ret = CwxAppHandler4Channel::open(arg); if (0 == ret){ UnistorTss* tss = (UnistorTss*)CwxTss::instance(); ///发送认证消息 CwxMsgBlock* block = NULL; if (UNISTOR_ERR_SUCCESS != UnistorPoco::packRecvAuth(tss->m_pWriter, block, 0, m_pApp->getConfig().getRecv().getUser().length()?m_pApp->getConfig().getRecv().getUser().c_str():"", m_pApp->getConfig().getRecv().getPasswd().length()?m_pApp->getConfig().getRecv().getPasswd().c_str():"", tss->m_szBuf2K)) { CWX_ERROR(("Failure to pack recv auth package, err=%s", tss->m_szBuf2K)); ret = channel()->removeHandler(this); if (0 != ret){ CWX_ERROR(("Failure to remove handler from channel")); } return -1; } (*m_handlers)[m_uiConnId] = this; block->send_ctrl().setMsgAttr(CwxMsgSendCtrl::NONE); ///发送消息 putMsg(block); } return 0; }
///发送topic状态表 int CwxMqInnerDispHandler::syncTopicState(CwxMqTss* pTss) { if (m_syncSession->m_topicIsChanged) { map<string, CWX_UINT8> topicState; map<string, CwxBinlogMgrCursor*>::iterator iter = m_syncSession->m_binlogCursor.begin(); while (iter != m_syncSession->m_binlogCursor.end()) { topicState.insert(pair<string, CWX_UINT8>(iter->first, iter->second->m_binlogMgr->getZkTopicState())); CWX_DEBUG(("sync topic:%s, state:%d", iter->first.c_str(), iter->second->m_binlogMgr->getZkTopicState())); iter++; } CwxMsgBlock* pBlock; int ret = CwxMqPoco::packTopicState(pTss->m_pWriter, pTss->m_pItemWriter, pBlock, 0, topicState, pTss->m_szBuf2K); if (ret != CWX_MQ_ERR_SUCCESS) { CWX_ERROR(("Failure to pack topicState err:%s", pTss->m_szBuf2K)); return -1; } ///根据svr类型,发送数据包 pBlock->send_ctrl().setConnId(CWX_APP_INVALID_CONN_ID); pBlock->send_ctrl().setSvrId(CwxMqApp::SVR_TYPE_INNER_DISP); pBlock->send_ctrl().setHostId(0); pBlock->send_ctrl().setMsgAttr(CwxMsgSendCtrl::NONE); if (!putMsg(pBlock)) { CwxCommon::snprintf(pTss->m_szBuf2K, 2047, "Failure to send topicState msg."); CWX_ERROR((pTss->m_szBuf2K)); CwxMsgBlockAlloc::free(pBlock); return -1; } m_syncSession->m_topicIsChanged = false; } return 0; }
void CwxEchoChannelEventHandler::replyMessage() { ///设置echo回复的消息类型,为请求的消息类型+1 m_recvMsgData->event().getMsgHeader().setMsgType(m_recvMsgData->event().getMsgHeader().getMsgType() + 1); ///设置echo回复的数据包长度 m_recvMsgData->event().getMsgHeader().setDataLen(m_recvMsgData->length()); ///创建回复的数据包 CwxMsgBlock* pBlock = CwxMsgBlockAlloc::malloc(m_recvMsgData->length() + CwxMsgHead::MSG_HEAD_LEN); ///拷贝数据包的包头 memcpy(pBlock->wr_ptr(), m_recvMsgData->event().getMsgHeader().toNet(), CwxMsgHead::MSG_HEAD_LEN); ///滑动block的写指针 pBlock->wr_ptr(CwxMsgHead::MSG_HEAD_LEN); ///拷贝数据包的数据 memcpy(pBlock->wr_ptr(), m_recvMsgData->rd_ptr(), m_recvMsgData->length()); ///滑动block的写指针 pBlock->wr_ptr(m_recvMsgData->length()); if (!putMsg(pBlock)) { CWX_ERROR(("Failure to put message")); CwxMsgBlockAlloc::free(pBlock); } m_ullMsgNum ++; if (m_ullMsgNum && !(m_ullMsgNum%10000)) { char szBuf[64]; CwxCommon::toString(m_ullMsgNum, szBuf, 10); CWX_INFO(("Recv echo message num:%s", szBuf)); } }
///连接关闭 int CwxProProxyApp::onConnClosed(CwxAppHandler4Msg& , CwxAppHandler4Msg& conn, CwxMsgHead const& , bool& ) { CwxMsgBlock* pBlock = CwxMsgBlockAlloc::malloc(0); pBlock->event().setSvrId(conn.getConnInfo().getSvrId()); pBlock->event().setHostId(conn.getConnInfo().getHostId()); pBlock->event().setConnId(conn.getConnInfo().getConnId()); pBlock->event().setEvent(CwxEventInfo::CONN_CLOSED); m_mqThreadPool->append(pBlock); return 0; }
///notice send msg by svr void CwxAppFramework::innerNoticeSendMsgBySvr(CwxAppFramework* pApp, CwxAppNotice* pNotice) { CwxMsgBlock* msg = (CwxMsgBlock*)pNotice->m_noticeArg; if (0 != pApp->onSendMsgBySvr(msg)) { if (msg->send_ctrl().isFailNotice()) { pApp->onFailSendMsg(msg); } if (msg) CwxMsgBlockAlloc::free(msg); } pNotice->m_noticeArg = NULL; }
///连接关闭 int CwxMqApp::onConnClosed(CwxAppHandler4Msg& conn) { if ((SVR_TYPE_RECV == conn.getConnInfo().getSvrId()) || (SVR_TYPE_MASTER == conn.getConnInfo().getSvrId())) { CwxMsgBlock* pBlock = CwxMsgBlockAlloc::malloc(0); pBlock->event().setSvrId(conn.getConnInfo().getSvrId()); pBlock->event().setHostId(conn.getConnInfo().getHostId()); pBlock->event().setConnId(conn.getConnInfo().getConnId()); ///设置事件类型 pBlock->event().setEvent(CwxEventInfo::CONN_CLOSED); m_recvThreadPool->append(pBlock); } else if (SVR_TYPE_MONITOR == conn.getConnInfo().getSvrId()) { ///若是监控的连接关闭,则必须释放先前所创建的string对象。 if (conn.getConnInfo().getUserData()) { delete (string*) conn.getConnInfo().getUserData(); conn.getConnInfo().setUserData(NULL); } } else { CWX_ASSERT(0); } return 0; }
///往master转发消息 bool UnistorHandler4Trans::transMsg(UnistorTss* , CWX_UINT32 uiTaskId, CwxMsgBlock* msg){ CwxMsgBlock* block = NULL; ///如果没有完成认证的连接,则失败 if (!m_uiAuthConnNum) return false; ///往master转发消息 block = CwxMsgBlockAlloc::malloc(CwxMsgHead::MSG_HEAD_LEN + msg->length()); CwxMsgHead header(msg->event().getMsgHeader()); header.setDataLen(msg->length()); header.setTaskId(uiTaskId); CWX_UINT8 ucAttr=header.getAttr(); header.setAttr(UnistorPoco::clearFromMaster(ucAttr)); memcpy(block->wr_ptr(), header.toNet(), CwxMsgHead::MSG_HEAD_LEN); memcpy(block->wr_ptr() + CwxMsgHead::MSG_HEAD_LEN, msg->rd_ptr(), msg->length()); block->wr_ptr( CwxMsgHead::MSG_HEAD_LEN + msg->length()); block->event().setTaskId(uiTaskId); block->send_ctrl().setMsgAttr(CwxMsgSendCtrl::FAIL_FINISH_NOTICE); if (!m_authConn[msg->event().getConnId()%m_uiAuthConnNum]->putMsg(block)){ CwxMsgBlockAlloc::free(block); return false; } return true; }
int UnistorHandler4Trans::onConnClosed() { list<CwxTaskBoardTask*> tasks; CwxTss* pThrEnv = CwxTss::instance(); CwxMsgBlock* msg = CwxMsgBlockAlloc::malloc(0); msg->event().setHostId(0); msg->event().setConnId(m_uiConnId); m_pApp->getTaskBoard().noticeConnClosed(msg, pThrEnv, tasks); if (!tasks.empty()) { list<CwxTaskBoardTask*>::iterator iter = tasks.begin(); while(iter != tasks.end()){ (*iter)->execute(pThrEnv); iter++; } tasks.clear(); } m_handlers->erase(m_uiConnId); m_bRebuildConn = true; m_bCanTrans = false; return -1; }
///notice send msg void CwxAppFramework::innerNoticeSendMsgByConn(CwxAppFramework* pApp, CwxAppNotice* pNotice) { CwxMsgBlock* msg = (CwxMsgBlock*)pNotice->m_noticeArg; CwxAppHandler4Msg* pConn = (CwxAppHandler4Msg*)pApp->m_pReactor->getHandlerByConnId(msg->send_ctrl().getConnId()); if (!pConn || (CwxAppConnInfo::ESTABLISHED != pConn->getConnInfo().getState())) { if (msg->send_ctrl().isFailNotice()) { pApp->onFailSendMsg(msg); } if (msg) CwxMsgBlockAlloc::free(msg); pNotice->m_noticeArg = NULL; return; } if (!msg->send_ctrl().isUndoConn()) { int ret = 0; if (msg->send_ctrl().isResumeConn()) { ret = pConn->reactor()->resumeHandler(pConn, CwxAppHandler4Base::READ_MASK); if (0 != ret) { CWX_ERROR(("Failure to resume handler, conn_id=[%u]", msg->send_ctrl().getConnId())); pConn->close(); } } else if (msg->send_ctrl().isSuspendConn()) { ret = pConn->reactor()->suspendHandler(pConn, CwxAppHandler4Base::READ_MASK); if (0 != ret) { CWX_ERROR(("Failure to resume handler, conn_id=[%u]", msg->send_ctrl().getConnId())); pConn->close(); } } } if (!pConn->putMsg(msg)) { if (msg->send_ctrl().isFailNotice()) { pApp->onFailSendMsg(msg); } if (msg) CwxMsgBlockAlloc::free(msg); pNotice->m_noticeArg = NULL; } }
///连接建立 int CwxMqApp::onConnCreated(CwxAppHandler4Msg& conn, bool&, bool&) { if ((SVR_TYPE_RECV == conn.getConnInfo().getSvrId()) || (SVR_TYPE_MASTER == conn.getConnInfo().getSvrId())) { CwxMsgBlock* pBlock = CwxMsgBlockAlloc::malloc(0); pBlock->event().setSvrId(conn.getConnInfo().getSvrId()); pBlock->event().setHostId(conn.getConnInfo().getHostId()); pBlock->event().setConnId(conn.getConnInfo().getConnId()); ///设置事件类型 pBlock->event().setEvent(CwxEventInfo::CONN_CREATED); ///将事件添加到消息队列 m_recvThreadPool->append(pBlock); } else if (SVR_TYPE_MONITOR == conn.getConnInfo().getSvrId()) { ///如果是监控的连接建立,则建立一个string的buf,用于缓存不完整的命令 string* buf = new string(); conn.getConnInfo().setUserData(buf); } else { CWX_ASSERT(0); } return 0; }
void CwxEchoThriftIf::Echo(echo_thrift::EchoData& _return, const std::string& echo_data) { EchoTss* tss = (EchoTss*)CwxTss::instance(); CwxMsgBlock* msg = CwxMsgBlockAlloc::malloc(echo_data.length()); memcpy(msg->wr_ptr(), echo_data.c_str(), echo_data.length()); msg->wr_ptr(echo_data.length()); msg->event().setSvrId(CwxEchoApp::SVR_TYPE_ECHO); msg->event().setEvent(CwxEventInfo::RECV_MSG); msg->event().setConnUserData(&tss->m_queue); tss->m_curId++; msg->event().m_ullArg = tss->m_curId; m_app->GetThreadPool()->append(msg); while(true) { if (tss->m_queue.dequeue(msg) != -1) { if (msg->event().m_ullArg == tss->m_curId) { _return.data.assign(msg->rd_ptr(), msg->length()); CwxMsgBlockAlloc::free(msg); return; } CwxMsgBlockAlloc::free(msg); } else { _return.data = ""; } } }
///echo请求的处理函数 int CwxEchoEventHandler::onRecvMsg(CwxMsgBlock*& msg, CwxTss* ) { ///设置echo回复的消息类型,为请求的消息类型+1 msg->event().getMsgHeader().setMsgType(msg->event().getMsgHeader().getMsgType() + 1); ///设置echo回复的数据包长度 msg->event().getMsgHeader().setDataLen(msg->length()); ///创建回复的数据包 CwxMsgBlock* pBlock = CwxMsgBlockAlloc::malloc(msg->length() + CwxMsgHead::MSG_HEAD_LEN); ///拷贝数据包的包头 memcpy(pBlock->wr_ptr(), msg->event().getMsgHeader().toNet(), CwxMsgHead::MSG_HEAD_LEN); ///滑动block的写指针 pBlock->wr_ptr(CwxMsgHead::MSG_HEAD_LEN); ///拷贝数据包的数据 memcpy(pBlock->wr_ptr(), msg->rd_ptr(), msg->length()); ///滑动block的写指针 pBlock->wr_ptr(msg->length()); ///设置回复消息的发送控制信息 pBlock->send_ctrl().reset(); ///设置回复消息对应连接的svr-id pBlock->send_ctrl().setSvrId(msg->event().getSvrId()); ///设置回复消息对应连接的host-id pBlock->send_ctrl().setHostId(msg->event().getHostId()); ///设置回复消息的连接id pBlock->send_ctrl().setConnId(msg->event().getConnId()); ///回复消息 if (0 != this->m_pApp->sendMsgByConn(pBlock)) { CWX_ERROR(("Failure to send msg")); return -1; } m_ullMsgNum ++; if (m_ullMsgNum && !(m_ullMsgNum%10000)) { char szBuf[64]; CwxCommon::toString(m_ullMsgNum, szBuf, 10); CWX_INFO(("Recv echo message num:%s", szBuf)); } return 1; }
int CwxMqApp::onConnCreated(CWX_UINT32 uiSvrId, CWX_UINT32 uiHostId, CWX_HANDLE handle, bool&) { CwxMsgBlock* msg = CwxMsgBlockAlloc::malloc(0); msg->event().setSvrId(uiSvrId); msg->event().setHostId(uiHostId); msg->event().setConnId(CWX_APP_INVALID_CONN_ID); msg->event().setIoHandle(handle); msg->event().setEvent(CwxEventInfo::CONN_CREATED); ///将消息放到线程池队列中,有内部的线程调用其处理handle来处理 if (SVR_TYPE_DISP == uiSvrId) { if (m_dispThreadPool->append(msg) <= 1) m_dispChannel->notice(); } else if (SVR_TYPE_QUEUE == uiSvrId) { if (m_mqThreadPool->append(msg) <= 1) m_mqChannel->notice(); } else { CWX_ASSERT(SVR_TYPE_MONITOR == uiSvrId); } return 0; }
///时钟函数 void CwxProProxyApp::onTime(CwxTimeValue const& current) { ///调用基类的onTime函数 CwxAppFramework::onTime(current); m_ttCurTime = current.sec(); ///检查超时 static CWX_UINT32 ttTimeBase = 0; ///<时钟回跳的base时钟 static CWX_UINT32 ttLastTime = 0; ///<上次检查时间 bool bClockBack = isClockBack(ttTimeBase, m_ttCurTime); if (bClockBack || (m_ttCurTime >= ttLastTime + 1)) { ttLastTime = m_ttCurTime; if (m_zkThreadPool) { ///发送超时检查到zk线程 CwxMsgBlock* pBlock = CwxMsgBlockAlloc::malloc(0); pBlock->event().setSvrId(SVR_PRO_TYPE_ZK); pBlock->event().setEvent(CwxEventInfo::TIMEOUT_CHECK); m_zkThreadPool->append(pBlock); } if (m_mqThreadPool) { ///发送超时检查到mq线程 CwxMsgBlock* pBlock = CwxMsgBlockAlloc::malloc(0); pBlock->event().setSvrId(SVR_PRO_TYPE_RECV); pBlock->event().setEvent(CwxEventInfo::TIMEOUT_CHECK); m_mqThreadPool->append(pBlock); } } }
///时钟函数 void CwxMqApp::onTime(CwxTimeValue const& current) { ///调用基类的onTime函数 CwxAppFramework::onTime(current); m_ttCurTime = current.sec(); ///检查超时 static CWX_UINT32 ttTimeBase = 0; ///<时钟回跳的base时钟 static CWX_UINT32 ttLastTime = m_ttCurTime; ///<上一次检查的时间 bool bClockBack = isClockBack(ttTimeBase, m_ttCurTime); if (bClockBack || (m_ttCurTime >= ttLastTime + 1)) { ttLastTime = m_ttCurTime; if (m_config.getCommon().m_bMaster) { CwxMsgBlock* pBlock = CwxMsgBlockAlloc::malloc(0); pBlock->event().setSvrId(SVR_TYPE_RECV); pBlock->event().setEvent(CwxEventInfo::TIMEOUT_CHECK); //将超时检查事件,放入事件队列 m_recvThreadPool->append(pBlock); } else { CwxMsgBlock* pBlock = CwxMsgBlockAlloc::malloc(0); pBlock->event().setSvrId(SVR_TYPE_MASTER); pBlock->event().setEvent(CwxEventInfo::TIMEOUT_CHECK); //将超时检查事件,放入事件队列 m_recvThreadPool->append(pBlock); } //若存在分发线程池,则往分发线程池append TIMEOUT_CHECK if (m_dispThreadPool) { CwxMsgBlock* pBlock = CwxMsgBlockAlloc::malloc(0); pBlock->event().setSvrId(SVR_TYPE_DISP); pBlock->event().setEvent(CwxEventInfo::TIMEOUT_CHECK); //将超时检查事件,放入事件队列 m_dispThreadPool->append(pBlock); } //若存在mq程池,则往mq线程池append TIMEOUT_CHECK if (m_mqThreadPool) { CwxMsgBlock* pBlock = CwxMsgBlockAlloc::malloc(0); pBlock->event().setSvrId(SVR_TYPE_QUEUE); pBlock->event().setEvent(CwxEventInfo::TIMEOUT_CHECK); //将超时检查事件,放入事件队列 m_mqThreadPool->append(pBlock); } } }
///echo请求的处理函数 int CwxMqRecvHandler::onRecvMsg(CwxMsgBlock*& msg, CwxTss* pThrEnv) { CwxMqTss* pTss = (CwxMqTss*) pThrEnv; if (!m_bCanWrite) { CWX_ERROR(("I am not master, can't recv msg so close it.")); m_pApp->noticeCloseConn(msg->event().getConnId()); return 1; } int iRet = CWX_MQ_ERR_SUCCESS; CWX_UINT64 ullSid = 0; do { ///binlog数据接收消息 if (CwxMqPoco::MSG_TYPE_RECV_DATA == msg->event().getMsgHeader().getMsgType()) { CwxKeyValueItem const* pData; char const* szTopic; if (!msg) { strcpy(pTss->m_szBuf2K, "No data."); CWX_DEBUG((pTss->m_szBuf2K)); iRet = CWX_MQ_ERR_ERROR; break; } unsigned long ulUnzipLen = 0; bool bZip = msg->event().getMsgHeader().isAttr(CwxMsgHead::ATTR_COMPRESS); //判断是否压缩数据 if (bZip) { //压缩数据,需要解压 //首先准备解压的buf if (!prepareUnzipBuf()) { iRet = CWX_MQ_ERR_ERROR; CwxCommon::snprintf(pTss->m_szBuf2K, 2047, "Failure to prepare unzip buf, size:%u", m_uiBufLen); CWX_ERROR((pTss->m_szBuf2K)); break; } ulUnzipLen = m_uiBufLen; //解压 if (!CwxZlib::unzip(m_unzipBuf, ulUnzipLen, (const unsigned char*) msg->rd_ptr(), msg->length())) { iRet = CWX_MQ_ERR_ERROR; CwxCommon::snprintf(pTss->m_szBuf2K, 2047, "Failure to unzip recv msg, msg size:%u, buf size:%u", msg->length(), m_uiBufLen); CWX_ERROR((pTss->m_szBuf2K)); break; } } if (CWX_MQ_ERR_SUCCESS != (iRet = CwxMqPoco::parseRecvData(pTss->m_pReader, bZip ? (char const*) m_unzipBuf : msg->rd_ptr(), bZip ? ulUnzipLen : msg->length(), pData, szTopic, pTss->m_szBuf2K))) { iRet = CWX_MQ_ERR_ERROR; //如果是无效数据,返回 CWX_ERROR(("Failure to parse the recieve msg, err=%s", pTss->m_szBuf2K)); break; } CwxBinLogMgr* binlogMgr = NULL; map<string, CwxBinLogMgr*>::iterator iter = m_binlogMgr.find(szTopic); if (iter == m_binlogMgr.end()) { binlogMgr = m_pApp->getTopicMgr()->getBinlogMgrByTopic(szTopic, true); if (!binlogMgr){ CwxCommon::snprintf(pTss->m_szBuf2K, 2047, "Invalid topic:%s", szTopic); CWX_ERROR((pTss->m_szBuf2K)); iRet = CWX_MQ_ERR_ERROR; break; } m_binlogMgr[szTopic] = binlogMgr; }else { binlogMgr = iter->second; } if (binlogMgr->getZkTopicState() != CWX_MQ_TOPIC_NORMAL) { CwxCommon::snprintf(pTss->m_szBuf2K, 2047, "Invlaid topic : %s.", szTopic); CWX_ERROR((pTss->m_szBuf2K)); iRet = CWX_MQ_ERR_ERROR; ///删除binlogMgr引用 m_binlogMgr.erase(szTopic); m_pApp->getTopicMgr()->freeBinlogMgrByTopic(szTopic, binlogMgr); break; } pTss->m_pWriter->beginPack(); pTss->m_pWriter->addKeyValue(CWX_MQ_D, pData->m_szData, pData->m_uiDataLen, pData->m_bKeyValue); pTss->m_pWriter->pack(); if (m_pApp->getCurSid() == 0) { m_pApp->setCurSid(CWX_MQ_MAX_BINLOG_FLUSH_COUNT + 1); } ullSid = m_pApp->nextSid(); CWX_UINT32 timestamp = time(NULL); if (0 != binlogMgr->append(ullSid, timestamp, 0, pTss->m_pWriter->getMsg(), pTss->m_pWriter->getMsgSize(), pTss->m_szBuf2K)) { CWX_ERROR((pTss->m_szBuf2K)); iRet = CWX_MQ_ERR_ERROR; break; } m_pApp->setCurTimestamp(timestamp); if (m_pApp->getStartSid() == 0) { m_pApp->setStartSid(ullSid); } } else { CwxCommon::snprintf(pTss->m_szBuf2K, 2047, "Invalid msg type:%u", msg->event().getMsgHeader().getMsgType()); CWX_ERROR((pTss->m_szBuf2K)); iRet = CWX_MQ_ERR_ERROR; break; } } while (0); CwxMsgBlock* pBlock = NULL; if (CWX_MQ_ERR_SUCCESS != CwxMqPoco::packRecvDataReply(pTss->m_pWriter, pBlock, msg->event().getMsgHeader().getTaskId(), iRet, ullSid, pTss->m_szBuf2K, pTss->m_szBuf2K)) { CWX_ERROR(("Failure to pack mq reply msg, err=%s", pTss->m_szBuf2K)); m_pApp->noticeCloseConn(msg->event().getConnId()); return 1; } pBlock->send_ctrl().setConnId(msg->event().getConnId()); pBlock->send_ctrl().setSvrId(CwxMqApp::SVR_TYPE_RECV); pBlock->send_ctrl().setHostId(0); pBlock->send_ctrl().setMsgAttr(CwxMsgSendCtrl::NONE); if (0 != m_pApp->sendMsgByConn(pBlock)) { CWX_ERROR(("Failure to reply error msg")); CwxMsgBlockAlloc::free(pBlock); m_pApp->noticeCloseConn(msg->event().getConnId()); } return 1; }
int CwxMqApp::monitorStats(char const* buf, CWX_UINT32 uiDataLen, CwxAppHandler4Msg& conn) { string* strCmd = (string*) conn.getConnInfo().getUserData(); strCmd->append(buf, uiDataLen); CwxMsgBlock* msg = NULL; string::size_type end = 0; do { CwxCommon::trim(*strCmd); end = strCmd->find('\n'); if (string::npos == end) { if (strCmd->length() > 10) { //无效的命令 strCmd->erase(); ///清空接受到的命令 ///回复信息 msg = CwxMsgBlockAlloc::malloc(1024); strcpy(msg->wr_ptr(), "ERROR\r\n"); msg->wr_ptr(strlen(msg->wr_ptr())); } else { return 0; } } else { if (memcmp(strCmd->c_str(), "stats", 5) == 0) { strCmd->erase(); ///清空接受到的命令 CWX_UINT32 uiLen = packMonitorInfo(); msg = CwxMsgBlockAlloc::malloc(uiLen); memcpy(msg->wr_ptr(), m_szBuf, uiLen); msg->wr_ptr(uiLen); } else if (memcmp(strCmd->c_str(), "quit", 4) == 0) { return -1; } else { //无效的命令 strCmd->erase(); ///清空接受到的命令 ///回复信息 msg = CwxMsgBlockAlloc::malloc(1024); strcpy(msg->wr_ptr(), "ERROR\r\n"); msg->wr_ptr(strlen(msg->wr_ptr())); } } } while (0); msg->send_ctrl().setConnId(conn.getConnInfo().getConnId()); msg->send_ctrl().setSvrId(CwxMqApp::SVR_TYPE_MONITOR); msg->send_ctrl().setHostId(0); msg->send_ctrl().setMsgAttr(CwxMsgSendCtrl::NONE); if (-1 == sendMsgByConn(msg)) { CWX_ERROR(("Failure to send monitor reply")); CwxMsgBlockAlloc::free(msg); return -1; } return 0; }
///分发mq channel的队列消息函数。返回值:0:正常;-1:队列停止 int CwxMqApp::dealMqFetchThreadQueueMsg(CwxMsgQueue* queue, CwxMqApp* app, CwxAppChannel* channel) { int iRet = 0; CwxMsgBlock* block = NULL; CwxAppHandler4Channel* handler = NULL; while (!queue->isEmpty()) { do { iRet = queue->dequeue(block); if (-1 == iRet) return -1; if ((block->event().getEvent() == CwxEventInfo::CONN_CREATED) && (block->event().getSvrId() == SVR_TYPE_QUEUE)) { if (channel->isRegIoHandle(block->event().getIoHandle())) { CWX_ERROR(("Handler[%] is register", block->event().getIoHandle())); break; } if (block->event().getSvrId() == SVR_TYPE_QUEUE) { handler = new CwxMqQueueHandler(app, channel); } else { CWX_ERROR(("Invalid svr_type[%d], close handle[%d]", block->event().getSvrId(), block->event().getIoHandle())); ::close(block->event().getIoHandle()); } handler->setHandle(block->event().getIoHandle()); if (0 != handler->open()) { CWX_ERROR(("Failure to register handler[%d]", handler->getHandle())); delete handler; break; } } else { CWX_ASSERT(block->event().getEvent() == CwxEventInfo::TIMEOUT_CHECK); CWX_ASSERT(block->event().getSvrId() == SVR_TYPE_QUEUE); app->getQueueMgr()->timeout(app->getCurTime()); } } while (0); CwxMsgBlockAlloc::free(block); block = NULL; } if (queue->isDeactived()) return -1; return 0; }
int CwxMqInnerDispHandler::recvReport(CwxMqTss* pTss) { int iRet = 0; CWX_UINT64 ullSid = 0; CWX_UINT32 uiChunk = 0; bool bZip = false; CwxMsgBlock* msg = NULL; do { if (!m_recvMsgData) { strcpy(pTss->m_szBuf2K, "No data."); CWX_ERROR(("Report package is empty, from:%s:%u", m_strPeerHost.c_str(), m_unPeerPort)); iRet = CWX_MQ_ERR_ERROR; break; } ///禁止重复report sid。若cunsor存在,表示已经报告过一次 if (m_syncSession) { iRet = CWX_MQ_ERR_ERROR; CwxCommon::snprintf(pTss->m_szBuf2K, 2048, "Can't report sync sid duplicate."); CWX_ERROR(("Report is duplicate, from:%s:%u", m_strPeerHost.c_str(), m_unPeerPort)); break; } ///若是同步sid的报告消息,则获取报告sid iRet = CwxMqPoco::parseInnerReportData(pTss->m_pReader, m_recvMsgData, ullSid, uiChunk, bZip, pTss->m_szBuf2K); if (CWX_MQ_ERR_SUCCESS != iRet) { CWX_ERROR(("Failure to parse report msg, err=%s, from:%s:%u", pTss->m_szBuf2K, m_strPeerHost.c_str(), m_unPeerPort)); break; } CWX_INFO(("Report info :%s:%u, sid=%s, chunk=%u, zip=%s", m_strPeerHost.c_str(), m_unPeerPort, CwxCommon::toString(ullSid, pTss->m_szBuf2K, 10), uiChunk, bZip?"yes":"no")); m_syncSession = new CwxMqInnerDispSession(m_pApp); m_syncSession->m_strHost = m_strPeerHost; m_syncSession->m_uiChunk = uiChunk; m_syncSession->m_bZip = bZip; if (m_syncSession->m_uiChunk) { if (m_syncSession->m_uiChunk > CwxMqConfigCmn::MAX_CHUNK_SIZE_KB) m_syncSession->m_uiChunk = CwxMqConfigCmn::MAX_CHUNK_SIZE_KB; if (m_syncSession->m_uiChunk < CwxMqConfigCmn::MIN_CHUNK_SIZE_KB) m_syncSession->m_uiChunk = CwxMqConfigCmn::MIN_CHUNK_SIZE_KB; m_syncSession->m_uiChunk *= 1024; } m_syncSession->reformSessionId(); ///将session加到session的map while (m_sessions.find(m_syncSession->m_ullSessionId) != m_sessions.end()) { m_syncSession->reformSessionId(); } m_sessions[m_syncSession->m_ullSessionId] = m_syncSession; m_ullSessionId = m_syncSession->m_ullSessionId; m_syncSession->addConn(this); if (0 != m_syncSession->init()) { CWX_ERROR(("Failure to init session min heap.")); break; } ///回复iRet的值 iRet = CWX_MQ_ERR_SUCCESS; ///创建binlog的读取cursor list<string> topics; m_pApp->getTopicMgr()->getAllTopics(topics); for(list<string>::iterator iter = topics.begin(); iter != topics.end(); iter++) { CwxBinLogMgr* binlogMgr = m_pApp->getTopicMgr()->getBinlogMgrByTopic(*iter); if (!binlogMgr) { ///binlogMgr被删除 CWX_ERROR(("Failure to get BinloMgr topic:%s", iter->c_str())); continue; } CwxBinLogCursor* pCursor = binlogMgr->createCurser(ullSid); if (!pCursor) { iRet = CWX_MQ_ERR_ERROR; strcpy(pTss->m_szBuf2K, "Failure to create cursor"); CWX_ERROR(("%s, from:%s:%u", pTss->m_szBuf2K, m_strPeerHost.c_str(), m_unPeerPort)); m_pApp->getTopicMgr()->freeBinlogMgrByTopic(*iter, binlogMgr); break; } CwxBinlogMgrCursor* item = new CwxBinlogMgrCursor(*iter, binlogMgr, pCursor); m_syncSession->m_binlogCursor[*iter] = item; m_syncSession->m_unReadyBinlogCursor.push_back(item); } m_syncSession->m_ullStartSid = ullSid; ///发送session id的消息 if (CWX_MQ_ERR_SUCCESS != CwxMqPoco::packReportDataReply(pTss->m_pWriter, msg, m_header.getTaskId(), m_syncSession->m_ullSessionId, pTss->m_szBuf2K)) { CWX_ERROR(("Failure to pack sync data reply, err=%s, from:%s:%u", pTss->m_szBuf2K, m_strPeerHost.c_str(), m_unPeerPort)); return -1; } msg->send_ctrl().setMsgAttr(CwxMsgSendCtrl::NONE); if (!putMsg(msg)) { CwxMsgBlockAlloc::free(msg); CWX_ERROR(("Failure push msg to send queue. from:%s:%u", m_strPeerHost.c_str(), m_unPeerPort)); return -1; } ///发送发一条binlog int iState = syncSendBinLog(pTss); if (-1 == iState) { iRet = CWX_MQ_ERR_ERROR; CWX_ERROR(("%s, from:%s:%u", pTss->m_szBuf2K, m_strPeerHost.c_str(), m_unPeerPort)); break; } else if (0 == iState) { ///产生continue的消息 channel()->regRedoHander(this); } return 0; }while(0); ///到此一定错误 CWX_ASSERT(CWX_MQ_ERR_SUCCESS != iRet); CwxMsgBlock* pBlock = NULL; if (CWX_MQ_ERR_SUCCESS != CwxMqPoco::packSyncErr(pTss->m_pWriter, pBlock, m_header.getTaskId(), iRet, pTss->m_szBuf2K, pTss->m_szBuf2K)) { CWX_ERROR(("Failure to create binlog reply package, err:%s", pTss->m_szBuf2K)); return -1; } pBlock->send_ctrl().setMsgAttr(CwxMsgSendCtrl::CLOSE_NOTICE); if (!putMsg(pBlock)) { CwxMsgBlockAlloc::free(pBlock); CWX_ERROR(("Failure push msg to send queue. from:%s:%u", m_strPeerHost.c_str(), m_unPeerPort)); return -1; } return 0; }
int CwxMqInnerDispHandler::recvNewConnection(CwxMqTss* pTss) { int iRet = 0; CWX_UINT64 ullSession = 0; CwxMsgBlock* msg = NULL; do { if (!m_recvMsgData) { strcpy(pTss->m_szBuf2K, "No data."); CWX_ERROR(("Session connect-report package is empty, from:%s:%u", m_strPeerHost.c_str(), m_unPeerPort)); iRet = CWX_MQ_ERR_ERROR; break; } ///禁止重复report sid。若cursor存在,表示已经报告过一次 if (m_syncSession) { iRet = CWX_MQ_ERR_ERROR; CwxCommon::snprintf(pTss->m_szBuf2K, 2048, "Can't report sync sid duplicatly."); CWX_ERROR(("Session connect-report is duplicate, from:%s:%u", m_strPeerHost.c_str(), m_unPeerPort)); break; } ///获取报告的session id iRet = CwxMqPoco::parseReportNewConn(pTss->m_pReader, m_recvMsgData, ullSession, pTss->m_szBuf2K); if (CWX_MQ_ERR_SUCCESS != iRet) { CWX_ERROR(("Failure to parse report new conn msg, err=%s, from:%s:%u", pTss->m_szBuf2K, m_strPeerHost.c_str(), m_unPeerPort)); break; } if (m_sessions.find(ullSession) == m_sessions.end()) { iRet = CWX_MQ_ERR_ERROR; char szTmp[64]; CwxCommon::snprintf(pTss->m_szBuf2K, 2048, "Session[%s] doesn't exist.", CwxCommon::toString(ullSession, szTmp, 10)); CWX_ERROR(("%s, from:%s:%u", pTss->m_szBuf2K, m_strPeerHost.c_str(), m_unPeerPort)); break; } m_syncSession = m_sessions.find(ullSession)->second; m_ullSessionId = m_syncSession->m_ullSessionId; m_syncSession->addConn(this); ///发送下一条binlog int iState = syncSendBinLog(pTss); if (-1 == iState) { iRet = CWX_MQ_ERR_ERROR; CWX_ERROR(("%s, from:%s:%u", pTss->m_szBuf2K, m_strPeerHost.c_str(), m_unPeerPort)); break; } else if (0 == iState) { ///产生continue消息 channel()->regRedoHander(this); } return 0; } while(0); ///到此一定错误 CWX_ASSERT(CWX_MQ_ERR_SUCCESS != iRet); if (CWX_MQ_ERR_SUCCESS != CwxMqPoco::packSyncErr(pTss->m_pWriter, msg, m_header.getTaskId(), iRet, pTss->m_szBuf2K, pTss->m_szBuf2K)) { CWX_ERROR(("Failure to pack sync data reply, err=%s, from:%s:%u", pTss->m_szBuf2K, m_strPeerHost.c_str(), m_unPeerPort)); return -1; } msg->send_ctrl().setMsgAttr(CwxMsgSendCtrl::CLOSE_NOTICE); if (!putMsg(msg)) { CwxMsgBlockAlloc::free(msg); CWX_ERROR(("Failure push msg to send queue. from:%s:%u", m_strPeerHost.c_str(), m_unPeerPort)); return -1; } return 0; }
int CwxMqInnerDispHandler::recvReply(CwxMqTss* pTss) { int iRet = CWX_MQ_ERR_SUCCESS; CWX_UINT64 ullSeq = 0; CwxMsgBlock* msg = NULL; do { if (!m_syncSession) { ///如果连接不是同步状态,则是错误 strcpy(pTss->m_szBuf2K, "Client no in sync state"); CWX_ERROR(("%s, from:%s:%u", pTss->m_szBuf2K, m_strPeerHost.c_str(), m_unPeerPort)); iRet = CWX_MQ_ERR_ERROR; break; } if (!m_recvMsgData) { strcpy(pTss->m_szBuf2K, "No data."); CWX_ERROR(("Sync reply package is empty, from:%s:%u", m_strPeerHost.c_str(), m_unPeerPort)); iRet = CWX_MQ_ERR_ERROR; break; } ///若是同步sid的报告消息,则获取报告的sid iRet = CwxMqPoco::parseSyncDataReply(pTss->m_pReader, m_recvMsgData, ullSeq, pTss->m_szBuf2K); if (CWX_MQ_ERR_SUCCESS != iRet) { CWX_ERROR(("Failure to parse sync_data reply package, err:%s, from:%s:%u", pTss->m_szBuf2K, m_strPeerHost.c_str(), m_unPeerPort)); break; } if (ullSeq != m_ullSendSeq) { char szTmp1[64]; char szTmp2[64]; iRet = CWX_MQ_ERR_ERROR; CwxCommon::snprintf(pTss->m_szBuf2K, 2047, "Seq[%s] is not same with the connection's[%s].", CwxCommon::toString(ullSeq, szTmp1, 10), CwxCommon::toString(m_ullSendSeq, szTmp2, 10)); CWX_ERROR(("%s, from:%s:%u", pTss->m_szBuf2K, m_strPeerHost.c_str(), m_unPeerPort)); break; } ///发送下一条binlog int iState = syncSendBinLog(pTss); if (-1 == iState) { CWX_ERROR(("%s, from:%s:%u", pTss->m_szBuf2K, m_strPeerHost.c_str(), m_unPeerPort)); return -1; ///关闭连接 } else if (0 == iState) { ///产生continue的消息 channel()->regRedoHander(this); } return 0; } while (0); ///到此一定错误 CWX_ASSERT(CWX_MQ_ERR_SUCCESS != iRet); if (CWX_MQ_ERR_SUCCESS != CwxMqPoco::packSyncErr(pTss->m_pWriter, msg, m_header.getTaskId(), iRet, pTss->m_szBuf2K, pTss->m_szBuf2K)) { CWX_ERROR(("Failure to pack sync data reply, err=%s, from:%s:%u", pTss->m_szBuf2K, m_strPeerHost.c_str(), m_unPeerPort)); return -1; } msg->send_ctrl().setMsgAttr(CwxMsgSendCtrl::CLOSE_NOTICE); if (!putMsg(msg)) { CwxMsgBlockAlloc::free(msg); CWX_ERROR(("Failure push msg to send queue. from:%s:%u", m_strPeerHost.c_str(), m_unPeerPort)); return -1; } return 0; }
///0:未发送一条binlog; ///1:发送了一条binlog; ///-1:失败; int CwxMqInnerDispHandler::syncSendBinLog(CwxMqTss* pTss) { int iRet = 0; CwxMsgBlock* pBlock = NULL; CWX_UINT32 uiKeyLen = 0; CWX_UINT32 uiTotalLen = 0; CWX_UINT64 ullSeq = m_syncSession->m_ullSeq; if (m_syncSession->m_topicIsChanged) { syncTopicState(pTss); } if (m_syncSession->m_uiChunk) pTss->m_pWriter->beginPack(); while (1) { if (m_syncSession->m_unReadyBinlogCursor.size()) { if (syncSeekToReportSid(pTss) != 0) return -1; } if (1 != (iRet = syncSeekToBinlog(pTss))) break; //设置移到下一个记录位置 m_syncSession->m_bNext = true; if (!m_syncSession->m_uiChunk) { iRet = syncPackOneBinLog(pTss->m_pWriter, pBlock, ullSeq, pTss->m_pBinlogData, pTss->m_szBuf2K); m_ullLastSid = m_syncSession->m_pBinlogCursor->m_pCursor->getHeader().getSid(); break; } else { iRet = syncPackMultiBinLog(pTss->m_pWriter, pTss->m_pItemWriter, pTss->m_pBinlogData, uiKeyLen, pTss->m_szBuf2K); m_ullLastSid = m_syncSession->m_pBinlogCursor->m_pCursor->getHeader().getSid(); if (1 == iRet) { uiTotalLen += uiKeyLen; if (uiTotalLen >= m_syncSession->m_uiChunk) break; } if (-1 == iRet) break; continue; } } if (-1 == iRet) return -1; if (!m_syncSession->m_uiChunk) { ///若不是chunk if (0 == iRet) return 0; ///没有数据 } else { if (0 == uiTotalLen) return 0; pTss->m_pWriter->pack(); if (CWX_MQ_ERR_SUCCESS != CwxMqPoco::packMultiSyncData(0, pTss->m_pWriter->getMsg(), pTss->m_pWriter->getMsgSize(), pBlock, ullSeq, m_syncSession->m_bZip, pTss->m_szBuf2K)) { return -1; } } ///根据svr类型,发送数据包 pBlock->send_ctrl().setConnId(CWX_APP_INVALID_CONN_ID); pBlock->send_ctrl().setSvrId(CwxMqApp::SVR_TYPE_INNER_DISP); pBlock->send_ctrl().setHostId(0); pBlock->send_ctrl().setMsgAttr(CwxMsgSendCtrl::NONE); if (!putMsg(pBlock)) { CwxCommon::snprintf(pTss->m_szBuf2K, 2047, "Failure to send binlog"); CWX_ERROR((pTss->m_szBuf2K)); CwxMsgBlockAlloc::free(pBlock); return -1; } m_ullSendSeq = ullSeq; m_syncSession->m_ullSeq++; return 1; ///发送了一条消息 }
int main(int argc, char** argv) { int iRet = parseArg(argc, argv); if (0 == iRet) return 0; if (-1 == iRet) return 1; CwxSockStream stream; CwxINetAddr addr(g_unPort, g_strHost.c_str()); CwxSockConnector conn; if (0 != conn.connect(stream, addr)) { printf("failure to connect ip:port: %s:%u, errno=%d\n", g_strHost.c_str(), g_unPort, errno); return 1; } CwxPackageWriter writer; CwxPackageReader reader; CwxMsgHead head; CwxMsgBlock* block = NULL; char szErr2K[2048]; char const* pErrMsg = NULL; CwxKeyValueItem item; if (g_file.length()) { item.m_szData = g_szData; item.m_uiDataLen = g_uiDataLen; } else { item.m_szData = (char*) g_data.c_str(); item.m_uiDataLen = g_data.length(); } do { if (CWX_MQ_ERR_SUCCESS != CwxMqPoco::packRecvData(&writer, block, 0, item, g_user.c_str(), g_passwd.c_str(), g_zip, szErr2K)) { printf("failure to pack message package, err=%s\n", szErr2K); iRet = 1; break; } if (block->length() != (CWX_UINT32) CwxSocket::write_n(stream.getHandle(), block->rd_ptr(), block->length())) { printf("failure to send message, errno=%d\n", errno); iRet = 1; break; } CwxMsgBlockAlloc::free(block); block = NULL; //recv msg if (0 >= CwxSocket::read(stream.getHandle(), head, block)) { printf("failure to read the reply, errno=%d\n", errno); iRet = 1; break; } if (CwxMqPoco::MSG_TYPE_RECV_DATA_REPLY != head.getMsgType()) { printf("recv a unknow msg type, msg_type=%u\n", head.getMsgType()); iRet = 1; break; } CWX_UINT64 ullSid; if (CWX_MQ_ERR_SUCCESS != CwxMqPoco::parseRecvDataReply(&reader, block, iRet, ullSid, pErrMsg, szErr2K)) { printf("failure to unpack reply msg, err=%s\n", szErr2K); iRet = 1; break; } if (CWX_MQ_ERR_SUCCESS != iRet) { printf("failure to send message, err_code=%d, err=%s\n", iRet, pErrMsg); iRet = 1; break; } iRet = 0; printf("success to send msg, data's sid=%s\n", CwxCommon::toString(ullSid, szErr2K, 10)); } while (0); if (g_szData) free(g_szData); if (block) CwxMsgBlockAlloc::free(block); stream.close(); return iRet; }