void UnistorHandler4Trans::checkTrans(UnistorApp* app, UnistorTss* tss){
    CWX_INFO(("UnistorHandler4Trans: ZK config is changed. master_idc:%s, is_master_idc:%s, master_host:%s, is_master=%s, sync_host:%s",
        tss->getMasterIdc(),
        tss->isMasterIdc()?"yes":"no",
        tss->getMasterHost(),
        tss->isMaster()?"yes":"no",
        tss->getSyncHost()));
    bool bTrans = false;
    string strTransMaster = "";
    if (tss->m_pZkConf && tss->m_pZkLock){
        if (tss->m_pZkConf->m_bMasterIdc){///如果是master idc
            if (!tss->m_pZkLock->m_bMaster){
                bTrans = true;
                strTransMaster = tss->m_pZkLock->m_strMaster;
            }else{
                bTrans = false;
            }
        }else{
            bTrans = false;
        }
    }
    if (!bTrans){
        ///关闭已有的所有连接
        map<CWX_UINT32, UnistorHandler4Trans*>::iterator iter = m_handlers->begin();
        while(iter != m_handlers->end()){
            iter->second->close();
            iter = m_handlers->begin();
        }
        CWX_ASSERT(m_handlers->size()==0);
        m_strMasterHost = "";
        m_uiAuthConnNum = 0;
        m_bRebuildConn = false;
        m_bCanTrans = false;
    }else{
        if (strTransMaster != m_strMasterHost){
            map<CWX_UINT32, UnistorHandler4Trans*>::iterator iter = m_handlers->begin();
            while(iter != m_handlers->end()){
                iter->second->close();
                iter = m_handlers->begin();
            }
            CWX_ASSERT(m_handlers->size()==0);
            m_strMasterHost = strTransMaster;
            m_uiAuthConnNum = 0;
            m_bRebuildConn = true;
            m_bCanTrans = false;
            rebuildConn(app);
        }
    }
}
Beispiel #2
0
int CwxAppEpoll::registerSignal(int signum,
                   CwxAppHandler4Base *event_handler)
{
    if (!m_bEnableSignal)
    {
        CWX_ASSERT(0);
        CWX_ERROR(("Epoll engine not support signal"));
        return -1;
    }
    if ((signum < 0) || (signum >= CWX_APP_MAX_SIGNAL_ID))
    {
        CWX_ERROR(("Invalid signal id[%d], range[0,%d]", signum, CWX_APP_MAX_SIGNAL_ID));
        return -1;
    }
    if (m_sHandler[signum])
    {
        CWX_ERROR(("Signal[%d]  exist.", signum));
        return -1;
    }
    struct sigaction sa;
    //set stop hander
    sa.sa_handler = 0;
    sa.sa_sigaction = CwxAppEpoll::sigAction;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags =SA_SIGINFO;
    if (-1 == sigaction(signum, &sa, NULL))
    {
        CWX_ERROR(("Failure register signal[%d] handler.", signum));
        return -1;
    }
    event_handler->setHandle(signum);
    m_sHandler[signum] = event_handler;
    return 0;

}
Beispiel #3
0
///用户自定义事件处理函数
int CwxMqRecvHandler::onUserEvent(CwxMsgBlock*& msg, CwxTss* pThrEnv) {
  CWX_ASSERT(m_pApp->getConfig().getCommon().m_type == CwxMqConfigCmn::MQ_TYPE_ZK);
  CwxMqTss* pTss = (CwxMqTss*)pThrEnv;
  if (EVENT_ZK_LOCK_CHANGE == msg->event().getEvent()) { ///master发生切换
    CwxMqZkLock* pLock = NULL;
    memcpy(&pLock, msg->rd_ptr(), sizeof(&pLock));
    if (pTss->m_pZkLock) {
      if (pTss->m_pZkLock->m_ullVersion > pLock->m_ullVersion) { ///采用旧版本
        delete pLock;
      }else { ///采用新版本
        delete pTss->m_pZkLock;
        pTss->m_pZkLock = pLock;
      }
    }else { ///采用新版本
      pTss->m_pZkLock = pLock;
    }
    CWX_INFO(("CwxMqRecvHandler: lock changed.master[%s:%s:%d], prev[%s:%s:%d]",
        pTss->m_pZkLock->m_strMaster.c_str(), pTss->m_pZkLock->m_strMasterInnerDispHost.c_str(),
        pTss->m_pZkLock->m_unMasterInnerDispPort, pTss->m_pZkLock->m_strPrev.c_str(),
        pTss->m_pZkLock->m_strPrevInnerDispHost.c_str(), pTss->m_pZkLock->m_unPrevInnerDispPort));
    configChange(pTss);
  }else {
    CWX_ERROR(("CwxMqRecvHandler: unknown event type:%u", msg->event().getEvent()));
    return 0;
  }

  return 1;
}
Beispiel #4
0
int CwxAppFramework::init(int argc, char** argv)
{
    int iRet = parse(argc, argv);
    if (0 != iRet)
    {
        help();
        return iRet;
    }
    if ( this->m_bCmdStop || this->m_bCmdRestart) return 0;

    this->destroy();

    if (0 != CwxTss::initTss())
    {
        CWX_ERROR(("Failure to init tss"));
        return -1;
    }
    //get app name
    CwxFile::getLastDirName(argv[0], m_strAppName);
    m_pTss = this->onTssEnv();
    CWX_ASSERT(m_pTss);
    m_pTss->getThreadInfo().setStartTime(time(NULL));
    m_pTss->getThreadInfo().setUpdateTime(time(NULL));
    m_pTss->getThreadInfo().setThreadNo(0);
    CwxTss::regTss(m_pTss);
 	return 0;
}
Beispiel #5
0
CwxAppHandler4Base* CwxAppEpoll::removeSignal(int signum)
{
    if (!m_bEnableSignal)
    {
        CWX_ASSERT(0);
        CWX_ERROR(("Epoll engine not support signal"));
        return NULL;
    }
    if ((signum < 0) || (signum >= CWX_APP_MAX_SIGNAL_ID))
    {
        CWX_ERROR(("Invalid signal id[%d], range[0,%d]", signum, CWX_APP_MAX_SIGNAL_ID));
        return NULL;
    }
    if (!m_sHandler[signum])
    {
        CWX_ERROR(("Signal[%d] doesn't exist.", signum));
        return NULL;
    }
    CwxAppHandler4Base* handler = m_sHandler[signum];
    struct sigaction sa;
    //set stop hander
    sa.sa_handler = SIG_DFL;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags =0x0;
    sigaction(signum, &sa, NULL);
    m_sHandler[signum] = NULL;
    return handler;
}
Beispiel #6
0
int CwxAppFramework::hook(void* arg)
{
    CwxAppFramework* pApp = (CwxAppFramework*)arg;
    if (!pApp->isStopped()){
        ///分发事件
        pApp->noticeEvent();
        //invoke the hook
        if (pApp->m_bEnableHook) pApp->onHook();
        //dispatch the fork event
        if (pApp->m_forkMgr.isForkEvent()){
            list<CwxAppForkEnv*> forks;
            pid_t  src_pid = getpid();
            pid_t  curPid = 0;
            pApp->m_forkMgr.getForkEnvs(forks);
            list<CwxAppForkEnv*>::iterator iter = forks.begin();
            CwxAppForkEnv* pForkEnv = NULL;
            while(iter != forks.end()){
                pForkEnv = *iter;
                curPid = pForkEnv->onFork();
                if (-1 == curPid){
                    CWX_ERROR(("Failure to fork"));
                }else if (0 == curPid){//child
                    CWX_ASSERT(src_pid != getpid());
                    iter++;
                    //delete the fork event in child process
                    while(iter != forks.end()){
                        delete *iter;
                        iter++;
                    }
                    pApp->m_bStopped = true;
                    pApp->m_pReactor->forkReinit();
                    //invoke child
                    pForkEnv->onChildEntry(pApp);
                    pApp->destroy();
                    pForkEnv->onChildMain();
                    delete pForkEnv;
                    return -1;
                }
                CWX_ASSERT(src_pid == getpid());
                delete *iter;
                //it's parent
                iter++;
            }
        }
    }
    return 0;
}
///检测超时的元素,key的expire时间超过uiCurTime的全部失效
void UnistorStoreMemCache::checkExpire(CWX_UINT32 uiCurTime, CWX_UINT32 uiBatchNum){
    CWX_UINT32 uiSlot=m_uiCurCheckSlotIndex;
    CWX_UINT32 uiPos=m_uiCurCheckSlotPos;
    CWX_UINT32 uiTotalSlot = m_cacheBufArrIndex + 1;
    CWX_UINT32 uiCheckNum = 0;
    UnistorStoreMemCacheItem* key=NULL;
    m_uiExpireNum = 0;
    for (; uiSlot<uiTotalSlot; uiSlot++){
        while(UNISTOR_STORE_MEM_CACHE_SLOT_SIZE >= uiPos + sizeof(UnistorStoreMemCacheItem)){
            key = (UnistorStoreMemCacheItem*)(m_cacheBufArr[uiSlot] + uiPos);
            if (UnistorStoreMemCacheItem::UNISTOR_MEM_ITEM_STATE_UNMALLOC == key->m_ucState){
                break;///<剩余的空间没有分配
            }else if (UnistorStoreMemCacheItem::UNISTOR_MEM_ITEM_STATE_USED == key->m_ucState){
                if (key->m_uiExpire && (key->m_uiExpire < uiCurTime)){///<疑似超时
                    m_arrExpiredItem[m_uiExpireNum++] = key;
                }
            }
            uiCheckNum++;
            uiPos += key->size();
            ///如果已经检查了指定的数量,则break。
            if (uiCheckNum >= m_uiMaxPerCheckExpireNum) break;
        }
        ///如果已经检查了指定的数量,则break。
        if (uiCheckNum >= m_uiMaxPerCheckExpireNum) break;
        uiPos = 0;///<从头开始
    }
    ///如果已经满了,则break
    if (uiCheckNum < m_uiMaxPerCheckExpireNum){
        ///本轮检测全部完成
        CWX_ASSERT(uiSlot == uiTotalSlot);
        m_uiCurCheckSlotIndex = 0;
        m_uiCurCheckSlotPos = 0;
    }else{
        m_uiCurCheckSlotIndex = uiSlot;
        m_uiCurCheckSlotPos = uiPos;
    }
    CWX_UINT32 uiIndex = 0;
    UnistorStoreMemCacheIter iter;
    while(uiIndex < m_uiExpireNum){
        if (uiIndex + uiBatchNum > m_uiExpireNum){
            uiBatchNum = m_uiExpireNum - uiIndex;
        }
        {
            ///获取写锁
            CwxWriteLockGuard<CwxRwLock> lock(&m_rwLock);
            for (CWX_UINT32 i=0; i<uiBatchNum; i++){
                iter.m_uiHash = UnistorStoreMemCacheItem::m_fnHash(m_arrExpiredItem[uiIndex]->getKey(), m_arrExpiredItem[uiIndex]->getKeyLen())%m_bucket_num;
                if (_findKey(m_arrExpiredItem[uiIndex], iter) && m_arrExpiredItem[uiIndex]->m_uiExpire && (m_arrExpiredItem[uiIndex]->m_uiExpire < uiCurTime)){
                    _remove(iter);
                }
                uiIndex++;
            } 

        }
    }
    m_uiExpireNum = 0;

}
Beispiel #8
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;
}
Beispiel #9
0
void CwxBinlogOp::doRecord(CWX_UINT32 uiRecord) {
  int iRet = 0;
  CWX_UINT64 offset = 0;
  printf("Seeking to binlog, record index=%u\n", uiRecord);
  map<CWX_UINT32/*rec_no*/, CWX_UINT32/*offset*/>::iterator iter;
  if (uiRecord + 1 > m_uiRecNum) {
    printf("Record Index[%u] doesn't exist, total record is %u\n", uiRecord,
      m_uiRecNum);
    return;
  }
  iter = m_recIndex.lower_bound(uiRecord + 1);

  CWX_ASSERT(iter != m_recIndex.end());
  CWX_UINT32 uiRecordSkip = 0;
  if (iter->first == uiRecord + 1) {
    offset = iter->second;
    uiRecordSkip = 0;
  } else {
    iter--;
    CWX_ASSERT(iter != m_recIndex.end());
    offset = iter->second;
    uiRecordSkip = uiRecord + 1 - iter->first;
  }

  CWX_UINT64 ullOldSid = m_pCursor->getHeader().getOffset();
  if (1 != m_pCursor->seek(offset)) {
    printf("Failure to seek binlog, error:%s\n", m_pCursor->getErrMsg());
    m_pCursor->seek(ullOldSid);
    return;
  }
  while (uiRecordSkip) {
    iRet = m_pCursor->next();
    if (0 == iRet) {
      printf("Skip to end.\n");
      return;
    } else if (0 > iRet) {
      printf("Failure to seek binlog, record index [%u], err=%s\n", uiRecord,
        m_pCursor->getErrMsg());
      m_pCursor->seek(ullOldSid);
      return;
    }
    uiRecordSkip--;
  }
}
Beispiel #10
0
int CwxAppEpoll::removeSignal(CwxAppHandler4Base *event_handler)
{
    if (!m_bEnableSignal)
    {
        CWX_ASSERT(0);
        CWX_ERROR(("Epoll engine not support signal"));
        return -1;
    }
    removeSignal(event_handler->getHandle());
    return 0;
}
Beispiel #11
0
//false:错误;true:解包正确。通过GetError()获取失败的原因。
bool CwxPackageReaderEx::unpack(char const* szMsg, CWX_UINT32 uiMsgLen, bool bIndex, bool bCaseSensive)
{
    int  iRet = 0;
    reset();
    m_uiPackBufLen = uiMsgLen;
    m_szPackMsg = szMsg;
    m_bIndex = bIndex;
    m_bCaseSensive = bCaseSensive;
    if (0 == uiMsgLen) return true;

    CwxCharCaseLess2 cmp(m_bCaseSensive);
    m_pKeyIndex = new CWX_PACKAGE_KEY_MAP(cmp);
    
    iRet = CwxPackageEx::getKeyValueNum(szMsg, uiMsgLen);
    if (0 > iRet)
    {
        strcpy(this->m_szErr, "It's not a valid package");
        return false;
    }
    m_uiKeyNum = iRet;
    if (m_uiTotalKeyNum < m_uiKeyNum)
    {
        if (m_pKeyValue) delete [] m_pKeyValue;
        m_uiTotalKeyNum = (m_uiKeyNum + KEY_VALUE_ALIGN -1)/KEY_VALUE_ALIGN;
        m_uiTotalKeyNum *= KEY_VALUE_ALIGN;
        m_pKeyValue = new CwxKeyValueItemEx[m_uiTotalKeyNum];
        memset(m_pKeyValue, 0x00, sizeof(CwxKeyValueItemEx) * m_uiTotalKeyNum);
    }
    CWX_UINT32 uiPos = 0;
    CWX_UINT32 uiIndex = 0;
    while(uiPos < m_uiPackBufLen)
    {
        if (uiIndex == m_uiKeyNum)
        {
            CwxCommon::snprintf(this->m_szErr, ERR_MSG_LEN, "The package should be kv[%u], but exceed.", m_uiKeyNum);
            CWX_ASSERT(0);
            return false;
        }
        if (-1 == (iRet = CwxPackageEx::getNextKey(this->m_szPackMsg + uiPos,
            m_uiPackBufLen - uiPos,
            this->m_pKeyValue[uiIndex])))
        {
            CwxCommon::snprintf(this->m_szErr, ERR_MSG_LEN, "Can't get the %dth key/value", uiIndex);
            return false;
        }
        if (0 == iRet) break; //finish
        if (m_bIndex) (*m_pKeyIndex)[this->m_pKeyValue[uiIndex].m_szKey] = &this->m_pKeyValue[uiIndex];
        uiIndex ++;
        uiPos += iRet;
        if (uiPos == uiMsgLen) return true; //finish.
    }
    return true;
}
Beispiel #12
0
int CwxAppEpoll::registerHandler(CWX_HANDLE handle,
                    CwxAppHandler4Base *event_handler,
                    int mask,
                    CWX_UINT32 uiMillSecond)
{
    if ((handle < 0) || (handle >= CWX_APP_MAX_IO_NUM))
    {
        CWX_ERROR(("Invalid io handle id[%d], range[0,%d]", handle, CWX_APP_MAX_IO_NUM));
        return -1;
    }
    ///若handle相等,是fork后的重新添加
    if (m_eHandler[handle].m_handler)
    {
        CWX_ERROR(("handler is registered, handle[%d]", (int)handle));
        return -1;
    }

    mask &=CwxAppHandler4Base::IO_MASK; ///只支持READ、WRITE、PERSIST、TIMEOUT四种掩码
    if (uiMillSecond) mask |= CwxAppHandler4Base::TIMEOUT_MASK;

    if (uiMillSecond)
    {
        CWX_ASSERT(-1 == event_handler->index());
        event_handler->m_ullTimeout = CwxDate::getTimestamp();
        event_handler->m_ullTimeout += uiMillSecond * 1000;
        if (!m_timeHeap.push(event_handler))
        {
            CWX_ERROR(("Failure to add handler to time-heap, io[%d]", handle));
            return -1;
        }
    }

    if (mask&CwxAppHandler4Base::RW_MASK) ///如果存在READ、WRITE的掩码,则注册
    {
        if (0 != addEvent(handle, mask))
        {
            if (uiMillSecond) 
                m_timeHeap.erase(event_handler); ///删除timeout
            return -1;
        }
    }
    m_eHandler[handle].m_handler = event_handler;
    m_eHandler[handle].m_mask = mask;
    return 0;
}
Beispiel #13
0
///echo请求的请求消息
int CwxEchoApp::onRecvMsg(CwxMsgBlock* msg, CwxAppHandler4Msg& conn, CwxMsgHead const& header, bool& bSuspendConn){

    msg->event().setSvrId(conn.getConnInfo().getSvrId());
    msg->event().setHostId(conn.getConnInfo().getHostId());
    msg->event().setConnId(conn.getConnInfo().getConnId());
    msg->event().setIoHandle(conn.getHandle());
    msg->event().setConnUserData(NULL);
    msg->event().setMsgHeader(header);
    msg->event().setEvent(CwxEventInfo::RECV_MSG);
    msg->event().setTimestamp(CwxDate::getTimestamp());
    ///不停止继续接受
    bSuspendConn = false;
    CWX_ASSERT (msg);
    ///将消息放到线程池队列中,有内部的线程调用其处理handle来处理
    m_threadPool->append(msg);
    return 0;

}
Beispiel #14
0
///收到消息的响应函数
int CwxMqApp::onRecvMsg(CwxAppHandler4Msg& conn, bool&) {
  if (SVR_TYPE_MONITOR == conn.getConnInfo().getSvrId()) {
    char szBuf[1024];
    ssize_t recv_size = CwxSocket::recv(conn.getHandle(), szBuf, 1024);
    if (recv_size <= 0) { //error or signal
      if ((0 == recv_size) || ((errno != EWOULDBLOCK) && (errno != EINTR))) {
        return -1; //error
      } else { //signal or no data
        return 0;
      }
    }
    ///监控消息
    return monitorStats(szBuf, (CWX_UINT32) recv_size, conn);
  } else {
    CWX_ASSERT(0);
  }
  return -1;
}
Beispiel #15
0
int CwxAppFramework::init(char const* app_name)
{
  parse();
  if ( this->m_bCmdStop || this->m_bCmdRestart) return 0;
  this->destroy();
  if (0 != CwxTss::initTss())
  {
    CWX_ERROR(("Failure to init tss"));
    return -1;
  }
  //get app name
  CwxFile::getLastDirName(app_name, m_strAppName);
  m_pTss = this->onTssEnv();
  CWX_ASSERT(m_pTss);
  m_pTss->getThreadInfo().setStartTime(time(NULL));
  m_pTss->getThreadInfo().setUpdateTime(time(NULL));
  m_pTss->getThreadInfo().setThreadNo(0);
  CwxTss::regTss(m_pTss);
  return 0;
}
Beispiel #16
0
///连接关闭
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;
}
Beispiel #17
0
///连接建立
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;
}
Beispiel #18
0
///收到消息
int CwxMqApp::onRecvMsg(CwxMsgBlock* msg,
                        CwxAppHandler4Msg& conn,
                        CwxMsgHead const& header,
                        bool&)
{
  if ((SVR_TYPE_RECV == conn.getConnInfo().getSvrId())
    || (SVR_TYPE_MASTER == conn.getConnInfo().getSvrId()))
  {
    msg->event().setSvrId(conn.getConnInfo().getSvrId());
    msg->event().setHostId(conn.getConnInfo().getHostId());
    msg->event().setConnId(conn.getConnInfo().getConnId());
    ///保存消息头
    msg->event().setMsgHeader(header);
    ///设置事件类型
    msg->event().setEvent(CwxEventInfo::RECV_MSG);
    ///将消息放到线程池队列中,有内部的线程调用其处理handle来处理
    m_recvThreadPool->append(msg);
    return 0;
  } else {
    CWX_ASSERT(0);
  }
  return 0;
}
Beispiel #19
0
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;
}
///释放关闭的session
void CwxMqInnerDispHandler::dealClosedSession(CwxMqApp* app, CwxMqTss* ) {
  list<CwxMqInnerDispSession*>::iterator iter;
  CwxMqInnerDispHandler* handler;
  ///获取用户object对象
  if (m_freeSession.begin() != m_freeSession.end()) {
    iter = m_freeSession.begin();
    while (iter != m_freeSession.end()) {
      CwxMqInnerDispSession* session = *iter;
      ///session必须是closed状态
      CWX_ASSERT((*iter)->m_bClosed);
      CWX_INFO(("Close sync session from host:%s", (*iter)->m_strHost.c_str()));
      if (session->m_binlogCursor.size()) {
        map<string, CwxBinlogMgrCursor*>::iterator cursor_iter = session->m_binlogCursor.begin();
        while(cursor_iter != session->m_binlogCursor.end()) {
          cursor_iter->second->m_binlogMgr->destoryCurser(cursor_iter->second->m_pCursor);
          app->getTopicMgr()->freeBinlogMgrByTopic(cursor_iter->first, cursor_iter->second->m_binlogMgr);
          delete cursor_iter->second;
          cursor_iter++;
        }
        session->m_binlogCursor.clear();
      }
      ///将session从session的map中删除
      m_sessions.erase((*iter)->m_ullSessionId);
      ///开始关闭连接
      map<CWX_UINT32, CwxMqInnerDispHandler*>::iterator conn_iter = (*iter)->m_conns.begin();
      while (conn_iter != (*iter)->m_conns.end()) {
        handler = conn_iter->second;
        (*iter)->m_conns.erase(handler->getConnId());
        handler->close(); ///此为同步调用
        conn_iter = (*iter)->m_conns.begin();
      }
      delete *iter;
      iter++;
    }
    m_freeSession.clear();
  }
}
///添加一个新连接
void CwxMqInnerDispSession::addConn(CwxMqInnerDispHandler* conn) {
  CWX_ASSERT(m_conns.find(conn->getConnId()) == m_conns.end());
  m_conns[conn->getConnId()] = conn;
}
Beispiel #22
0
void CwxBinlogOp::doSid(CWX_UINT64 ullSid) {
  int iRet = 0;
  CWX_UINT64 offset = 0;
  char szBuf1[64], szBuf2[64];
  printf("Seeking to binlog, sid=%s\n", CwxCommon::toString(ullSid, szBuf1));
  map<CWX_UINT64/*sid*/, CWX_UINT32/*offset*/>::iterator iter;

  if (ullSid < m_ullMinSid) {
    printf("Sid[%s] is less than min sid[%s], it doesn't exist\n",
      CwxCommon::toString(ullSid, szBuf1),
      CwxCommon::toString(m_ullMinSid, szBuf2));
    return;
  }
  if (ullSid > m_ullMaxSid) {
    printf("Sid[%s] is more than max sid[%s], it doesn't exist\n",
      CwxCommon::toString(ullSid, szBuf1),
      CwxCommon::toString(m_ullMaxSid, szBuf2));
    return;
  }
  iter = m_sidIndex.lower_bound(ullSid);

  CWX_ASSERT(iter != m_sidIndex.end());
  if (iter->first == ullSid) {
    offset = iter->second;
  } else {
    iter--;
    CWX_ASSERT(iter != m_sidIndex.end());
    offset = iter->second;
  }

  CWX_UINT32 i = 0;
  CWX_UINT64 ullOldSid = m_pCursor->getHeader().getOffset();
  bool bFind = false;
  if (1 != m_pCursor->seek(offset)) {
    printf("Failure to seek binlog, error:%s\n", m_pCursor->getErrMsg());
    m_pCursor->seek(ullOldSid);
    return;
  }
  for (i = 0; i < BINLOG_INDEX_INTERNAL; i++) {
    if (m_pCursor->getHeader().getSid() == ullSid) {
      bFind = true;
      printf("Find sid=%s\n", CwxCommon::toString(ullSid, szBuf1));
      return;
    }
    iRet = m_pCursor->next();
    if (1 == iRet)
      continue;
    if (0 == iRet) {
      printf("Can't find sid=%s\n", CwxCommon::toString(ullSid, szBuf1));
      m_pCursor->seek(ullOldSid);
      return;
    } else if (0 > iRet) {
      printf("Failure to seek binlog, err=%s\n", m_pCursor->getErrMsg());
      m_pCursor->seek(ullOldSid);
      return;
    }
  }
  printf("Can't find binlog, sid=%s\n", CwxCommon::toString(ullSid, szBuf1));
  m_pCursor->seek(ullOldSid);

}
int CwxAppHandler4Channel::onOutput ()
{
    int result = 0;
    bool bCloseConn = false;
    // The list had better not be empty, otherwise there's a bug!
    if (NULL == this->m_curSndingMsg)
    {
        CWX_ASSERT(m_uiSendByte==0);
        while(1)
        {
            result = this->getNextMsg();
            if (0 == result) return this->cancelWakeup();
            if (CWX_CHECK_ATTR(this->m_curSndingMsg->send_ctrl().getMsgAttr(), CwxMsgSendCtrl::BEGIN_NOTICE))
            {
                if (-1 == onStartSendMsg(m_curSndingMsg))
                {
                    CwxMsgBlockAlloc::free(this->m_curSndingMsg);
                    this->m_curSndingMsg = NULL;
                    continue; //next msg;
                }
            }//end if (this->m_curSndingMsg->IsBeginNotice())
            //it's a msg which need be sent.
            break; //break while
        }//end while
    }
    //has message
    result = this->nonBlockSend();
    if (0 == result)
    {// Partial send.
        CWX_ASSERT (errno == EWOULDBLOCK);
        return 0;
    }
    else if (1 == result)
    {//finish
        bCloseConn = CWX_CHECK_ATTR(this->m_curSndingMsg->send_ctrl().getMsgAttr(), CwxMsgSendCtrl::CLOSE_NOTICE);
        this->m_uiSendByte = 0;
        if (CWX_CHECK_ATTR(this->m_curSndingMsg->send_ctrl().getMsgAttr(), CwxMsgSendCtrl::FINISH_NOTICE)){
            CWX_UINT32 uiResume = onEndSendMsg(m_curSndingMsg);
            if (CwxMsgSendCtrl::RESUME_CONN == uiResume)
            {
                if (0 != channel()->resumeHandler(this, CwxAppHandler4Base::READ_MASK))
                {
                    CWX_ERROR(("Failure to resume handler with conn_id[%d]", getHandle()));
                    return -1;
                }
            }
            else if (CwxMsgSendCtrl::SUSPEND_CONN == uiResume)
            {
                if (0 != channel()->suspendHandler(this, CwxAppHandler4Base::READ_MASK))
                {
                    CWX_ERROR(("Failure to suspend handler with conn_id[%d]", getHandle()));
                    return -1;
                }
            }
        }
        if (bCloseConn)
        {
            return -1;
        }
        if (m_curSndingMsg)
        {
            CwxMsgBlockAlloc::free(m_curSndingMsg);
            this->m_curSndingMsg = NULL;
        }
        return 0;
    }
    else
    {//failure
        if (m_curSndingMsg->send_ctrl().isFailNotice())
        {
            onFailSendMsg(m_curSndingMsg);
        }
        if (m_curSndingMsg) CwxMsgBlockAlloc::free(m_curSndingMsg);
        this->m_curSndingMsg = NULL;
        return -1;
    }
    return -1;
}
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;
}
Beispiel #25
0
void UnistorStoreMemCache::insert(char const* szKey,
            CWX_UINT16 unKeyLen,
            char const* szData,
            CWX_UINT32 uiDataLen,
            CWX_UINT32* uiExpire)
{
    ///key的长度不能为0
    if (!unKeyLen) return;
    CWX_UINT32 uiOldExpire = 0;
    CWX_UINT32 uiIndex = 0;
    char key_buf[UnistorStoreMemCacheItem::calKeySize(unKeyLen , 0)];
    UnistorStoreMemCacheItem* key = (UnistorStoreMemCacheItem*)key_buf;
    memcpy(key->m_szBuf, szKey, unKeyLen);
    key->m_unKeyLen = unKeyLen;
    UnistorStoreMemCacheIter iter;

    CWX_UINT32 uiKeySize = UnistorStoreMemCacheItem::calKeySize(unKeyLen , uiDataLen);
    ///若key的空间大小大于slot,则不cache
    if (uiKeySize > UNISTOR_STORE_MEM_CACHE_MAX_ITEM_SIZE) return;

    iter.m_uiHash = UnistorStoreMemCacheItem::m_fnHash(key->getKey(), key->getKeyLen())%m_bucket_num;
    {
        CwxWriteLockGuard<CwxRwLock> lock(&m_rwLock);
        ///如果key存在
        if(_findKey(key, iter)){
            if (uiKeySize == iter.m_pFind->size()){///属于同一个slot
                ///修改空间
                m_usedDataSize -= iter.m_pFind->getDataLen();
                m_usedDataSize += uiDataLen;
                iter.m_pFind->m_uiDataLen = uiDataLen;
                if (uiExpire) iter.m_pFind->m_uiExpire = *uiExpire;
                if (uiDataLen){
                    memcpy((char*)iter.m_pFind->getData(), szData, uiDataLen);  
                }
                uiIndex = iter.m_pFind->index();
                _touch(iter.m_pFind, uiIndex);
                return;
            }
            uiOldExpire = iter.m_pFind->m_uiExpire;
            ///属于不同的slot,首先溢出,此时拥有hash锁、链表锁、及统计锁
            _remove(iter);
        }
        ///计算索引
        uiIndex = UnistorStoreMemCacheItem::calKeyIndex(unKeyLen , uiDataLen);
        ///优先使用空闲的key
        if (m_chainArr[uiIndex].m_freeHead){
            key = m_chainArr[uiIndex].m_freeHead;
            m_chainArr[uiIndex].m_freeHead = m_chainArr[uiIndex].m_freeHead->m_next;
            ///修改空间
            m_chainArr[uiIndex].m_uiFreeNum--;
            m_freeSize -= uiKeySize;
            m_freeCapacity -= (uiKeySize - sizeof(UnistorStoreMemCacheItem));
            m_freeItemCount --;
        }else if ((m_cacheBufArrIndex + 1 < m_cacheBufArrSize) ||  ///从新内存分配key
            (m_cacheBufArrPos + uiKeySize < UNISTOR_STORE_MEM_CACHE_SLOT_SIZE))
        {
            if (m_cacheBufArrPos + uiKeySize > UNISTOR_STORE_MEM_CACHE_SLOT_SIZE){///<使用新slot
                m_cacheBufArrIndex ++;
                m_cacheBufArrPos = 0;
            }
            ///分配新空间
            key = (UnistorStoreMemCacheItem*)(m_cacheBufArr[m_cacheBufArrIndex] + m_cacheBufArrPos);
            m_cacheBufArrPos += uiKeySize;
        }else if (m_chainArr[uiIndex].m_usedTail){///释放已有空间
            key = m_chainArr[uiIndex].m_usedTail;
            iter.m_uiHash = UnistorStoreMemCacheItem::m_fnHash(key->getKey(), key->getKeyLen())%m_bucket_num;
            _findKey(key, iter);
            if (iter.m_pFind != key){
                CWX_ASSERT(0);
            }
            ///从hash中删除key
            _removeKey(iter);
            m_chainArr[uiIndex].m_usedTail = m_chainArr[uiIndex].m_usedTail->m_prev;
            if (!m_chainArr[uiIndex].m_usedTail){
                m_chainArr[uiIndex].m_usedHead = NULL;
            }else{
                m_chainArr[uiIndex].m_usedTail->m_next = NULL;
            }
            m_chainArr[uiIndex].m_uiUsedNum--;
            m_usedSize -= uiKeySize;
            m_usedCapacity -= uiKeySize - sizeof(UnistorStoreMemCacheItem);
            m_usedDataSize -= key->m_uiDataLen + key->m_unKeyLen;
            m_cachedKeyCount--;
            m_cachedItemCount--;
        }else{ ///没有空间可用,不cache
            return ;
        }
        ///copy数据
        key->m_uiKeyIndex = uiIndex; ///<设置key的index
        key->m_unKeyLen = unKeyLen;
        key->m_uiDataLen = uiDataLen;
        key->m_ucState = UnistorStoreMemCacheItem::UNISTOR_MEM_ITEM_STATE_USED;
        key->m_uiExpire = uiExpire?*uiExpire:uiOldExpire;
        if (unKeyLen)  memcpy((char*)key->getKey(), szKey, unKeyLen);
        if (uiDataLen) memcpy((char*)key->getData(), szData, uiDataLen);
        _addKey(uiIndex, uiKeySize, key);
    }
}
Beispiel #26
0
int CwxAppFramework::noticeFork(CwxAppForkEnv* pForkEnv){
    CWX_ASSERT(pForkEnv);
    m_forkMgr.append(pForkEnv);
    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;
}
void CwxMqInnerDispHandler::doEvent(CwxMqApp* app, CwxMqTss* tss, CwxMsgBlock*& msg) {
  if (CwxEventInfo::CONN_CREATED == msg->event().getEvent()) { ///连接建立
    CwxAppChannel* channel = app->getInnerDispChannel();
    if (channel->isRegIoHandle(msg->event().getIoHandle())) {
      CWX_ERROR(("Handler[%d] is register, it's a big bug. exit....", msg->event().getIoHandle()));
      app->stop();
      return ;
    }
    CwxMqInnerDispHandler* pHandler = new CwxMqInnerDispHandler(app, channel,
        app->reactor()->getNextConnId());
    ///获取连接的来源信息
    CwxINetAddr remoteAddr;
    CwxSockStream stream(msg->event().getIoHandle());
    stream.getRemoteAddr(remoteAddr);
    pHandler->m_unPeerPort = remoteAddr.getPort();
    if (remoteAddr.getHostIp(tss->m_szBuf2K, 2047)) {
      pHandler->m_strPeerHost = tss->m_szBuf2K;
    }
    ///设置handle的io后,open handler
    pHandler->setHandle(msg->event().getIoHandle());
    if (0 != pHandler->open()) {
      CWX_ERROR(("Failure to register sync handler[%d], from:%s:%u", pHandler->getHandle(),
          pHandler->m_strPeerHost.c_str(), pHandler->m_unPeerPort));
      delete pHandler;
      return ;
    }
    ///设置对象的tss对象
    pHandler->m_tss = (CwxMqTss*)CwxTss::instance();
    CWX_INFO(("Accept inner-sync connection from %s:%u", pHandler->m_strPeerHost.c_str(), pHandler->m_unPeerPort));
  } else if (EVENT_ZK_TOPIC_CHANGE == msg->event().getEvent()) { ///topic变化通知
    map<string, CWX_UINT8>* changedTopics = NULL;
    memcpy(&changedTopics, msg->rd_ptr(), sizeof(changedTopics));
    if (changedTopics->size()) {
      map<string, CWX_UINT8>::iterator iter = changedTopics->begin();
      for (;iter != changedTopics->end(); iter++) {
        map<CWX_UINT64, CwxMqInnerDispSession*>::iterator ses_iter = m_sessions.begin();
        for (;ses_iter != m_sessions.end();ses_iter++) {
          ses_iter->second->m_topicIsChanged = true;
          ///忽略topic/状态改变
          if ( iter->second == CWX_MQ_TOPIC_DELETE ||
              ses_iter->second->m_binlogCursor.find(iter->first) != ses_iter->second->m_binlogCursor.end()) continue;
          {///新增topic
            CwxBinLogMgr* binlogMgr = app->getTopicMgr()->getBinlogMgrByTopic(iter->first);
            if (!binlogMgr) {
              CWX_ERROR(("Failure to get binlogMgr by topic:%s", iter->first.c_str()));
              break;
            }
            CwxBinLogCursor* pCursor = binlogMgr->createCurser(ses_iter->second->m_ullStartSid);
            if (!pCursor) {
              CWX_ERROR(("Failure to createCursor by topic:%s", iter->first.c_str()));
              app->getTopicMgr()->freeBinlogMgrByTopic(iter->first, binlogMgr);
              break;
            }
            CwxBinlogMgrCursor* item = new CwxBinlogMgrCursor(iter->first, binlogMgr, pCursor);
            ses_iter->second->m_unReadyBinlogCursor.push_back(item);
            ses_iter->second->m_binlogCursor[iter->first] = item;
          }
        }
      }
    }
    delete changedTopics;
  } else {
    CWX_ERROR(("Recv unkown event:%d", msg->event().getEvent()));
    CWX_ASSERT(msg->event().getEvent() == CwxEventInfo::TIMEOUT_CHECK);
    CWX_ASSERT(msg->event().getSvrId() == CwxMqApp::SVR_TYPE_INNER_DISP);
  }
}
///handle close
int CwxAppHandler4UnixConn::close(CWX_HANDLE )
{
    CWX_UINT16 ucLocState = m_conn.getState();
    char const* szState;
    int iCloseReturn=0;

    if (getApp()->isStopped())
    {
		if (-1 != this->index()) reactor()->cancelTimer(this);
        delete this;
        return 0;
    }

    switch(ucLocState)
    {
    case CwxAppConnInfo::IDLE:
        szState = "IDLE"; ///一定没有在reactor注册
        break;
    case CwxAppConnInfo::CONNECTING:
        szState = "CONNECTING";///可能在重连的时候再reactor注册
        CWX_ERROR(("Failure to connect to unix-file:%s, errno=%d",
            m_strConnectPathFile.c_str(),
            getConnErrNo()));
        if (reactor()) reactor()->removeHandler(this);
        break;
    case CwxAppConnInfo::TIMEOUT:
        szState = "TIMEOUT"; ///可能注册了timeout
        if (-1 != this->index()) reactor()->cancelTimer(this);
        break;
    case CwxAppConnInfo::ESTABLISHING:
        szState = "ESTABLISHING";///可能注册了消息收发
        if (CWX_INVALID_HANDLE != getHandle())
            if (reactor()) reactor()->removeHandler(this, false);
        break;
    case CwxAppConnInfo::ESTABLISHED:
        szState = "ESTABLISHED";///一定注册了消息收发
        if (CWX_INVALID_HANDLE != getHandle())
            if (reactor()) reactor()->removeHandler(this, false);
        break;
    case CwxAppConnInfo::FAILED:
        szState = "FAILED";///一定没有注册消息收发
        break;
    default:
        szState = "Unknown";
        CWX_ASSERT(0);
        break;
    }
    if (CWX_INVALID_HANDLE != getHandle())
    {
        CWX_DEBUG(("Connection closed. State = %s, unix file=%s, Active-Close=%s", 
            szState,
            m_strConnectPathFile.c_str(),
            m_conn.isActiveClose()?"yes":"no"));
    }

    m_conn.setState(CwxAppConnInfo::FAILED);

    //reconnection or close
    if (CwxAppConnInfo::ESTABLISHED == ucLocState)
    {
        //re-dispatch all msg
        while(this->getNextMsg() == 1)
        {
            if (this->m_curSndingMsg && m_curSndingMsg->send_ctrl().isFailNotice())
            {
                this->getApp()->onFailSendMsg(m_curSndingMsg);
            }
            if (m_curSndingMsg) CwxMsgBlockAlloc::free(m_curSndingMsg);
            this->m_curSndingMsg = NULL;
        }
        iCloseReturn = this->getApp()->connClosed(*this);
        m_conn.setFailConnNum(1);
        //remove recieved data.
        if (this->m_recvMsgData) CwxMsgBlockAlloc::free(this->m_recvMsgData);
        this->m_recvMsgData = NULL;
    }
    else if (m_conn.isActiveConn())
    {
        m_conn.setFailConnNum(m_conn.getFailConnNum() + 1);
        iCloseReturn = this->getApp()->onFailConnect(*this);
    }

    if (getHandle () != CWX_INVALID_HANDLE)
    {
        ::close(getHandle());
        setHandle(CWX_INVALID_HANDLE);
    }

    if (m_conn.isNeedReconnect() && (iCloseReturn>=0))
    {
        CWX_UINT32 uiInternal = 0;
        if (m_conn.isReconn())
        {
            uiInternal = m_conn.getReconnDelay();
            m_conn.setReconn(false);
        }
        else
        {
            if (iCloseReturn > 0)
            {
                uiInternal = iCloseReturn;
            }
            else
            {
                uiInternal = 2 * m_conn.getMinRetryInternal() * getConnInfo().getFailConnNum();
                if (uiInternal > getConnInfo().getMaxRetryInternal()) uiInternal = getConnInfo().getMaxRetryInternal();
                uiInternal *= 1000;
            }
        }

        CWX_DEBUG(("Reconnect to address %s after %d mili-second.", m_strConnectPathFile.c_str(), uiInternal));
        if (uiInternal)
        {
            m_conn.setState(CwxAppConnInfo::TIMEOUT);
            if (this->reactor()->scheduleTimer(this, CwxTimeValue(uiInternal/1000, (uiInternal%1000) * 1000)) == -1)
            {
                CWX_ERROR(("Failure schedule_timer to noticeReconnect for conn id[%u]", m_conn.getConnId()));
                if (reactor()) reactor()->removeHandlerByConnId(m_conn.getConnId());
                delete this;
                return 0;
            }
        }
        else
        {
            if (-1 == getApp()->getUnixConnector()->connect(this,
                m_strConnectPathFile.c_str()))
            {
                CWX_ERROR(("Failure to reconnect unix-file=%s, errno=%d",
                    m_strConnectPathFile.c_str(),
                    errno));
                this->close();
            }
        }

    }
    else
    {
        reactor()->removeFromConnMap(m_conn.getConnId());
        getApp()->getHandlerCache()->cacheUnixHandle(this);
    }

    return 0;
}