/**
     * post_packet is async version of send_packet. donot wait for response packet.
     */
    int ObClientManager::do_post_packet(const ObServer& server, ObPacket* packet,
        tbnet::IPacketHandler* handler, void* args) const
    {
      int rc = OB_SUCCESS;
      if (NULL == packet) 
      {
        rc = OB_INVALID_ARGUMENT;
      }
      else if (!inited_) 
      {
        rc = OB_NOT_INIT;
        TBSYS_LOG(ERROR, "cannot post packet, ClientManager not initialized.");
        packet->free();
      }
      else
      {
        bool send_ok = connmgr_->sendPacket(server.get_ipv4_server_id(), packet, handler, args);
        if (!send_ok)
        {
          rc = OB_PACKET_NOT_SENT;
          TBSYS_LOG(WARN, "cannot post packet, maybe send queue is full or disconnect.dest_server:%s",
              server.to_cstring());
          packet->free();
        }
      } 

      return rc;
    }
    /*
     * send a packet to server %server and wait response packet
     * @param server send to server
     * @param packet send packet object, must be allocate on heap, 
     * if send_packet failed, packet will be free by send_packet.
     * @param timeout max wait time interval
     * @param [out] response  response packet from remote server, allocated on heap, 
     * must be free by user who call the send_packet. response not NULL when return success.
     * @return OB_SUCCESS on success or other on failure.
     */
    int ObClientManager::do_send_packet(const ObServer & server, 
        ObPacket* packet, const int64_t timeout, ObPacket* &response) const
    {
      response = NULL;
      int rc = OB_SUCCESS;
      if (NULL == packet) 
      {
        rc = OB_INVALID_ARGUMENT;
      }
      else if (!inited_) 
      {
        rc = OB_NOT_INIT;
        TBSYS_LOG(ERROR, "cannot send packet, ClientManager not initialized.");
        packet->free();
        packet = NULL;
      }
      else if (OB_SUCCESS != error_)
      {
        rc = error_;
        packet->free();
        TBSYS_LOG(ERROR, "prev_error=%d", error_);
      }

      common::WaitObject* wait_object = NULL;
      if (OB_SUCCESS == rc)
      {
        wait_object =  waitmgr_->create_wait_object();
        if (NULL == wait_object)
        {
          TBSYS_LOG(ERROR, "cannot send packet, cannot create wait object");
          rc = OB_ERROR;
        }

      }
      if (OB_SUCCESS == rc) 
      {
        if (timeout > max_request_timeout_)
        {
          max_request_timeout_ = timeout;
          connmgr_->setDefaultQueueTimeout(0, static_cast<int32_t>(max_request_timeout_ / 1000));
        }
        // caution! wait_object set no free, it means response packet
        // not be free by wait_object, must be handled by user who call send_packet.
        // MODIFY: wait_object need free the response packet not handled.
        // wait_object->set_no_free();
        int packet_code = packet->get_packet_code();
        bool send_ok = connmgr_->sendPacket(server.get_ipv4_server_id(), packet, NULL, 
            reinterpret_cast<void*>(wait_object->get_id()));
        if (send_ok)
        {
          send_ok = wait_object->wait(timeout);
          if (!send_ok)
          {
            TBSYS_LOG(ERROR, "wait packet(%d) response timeout, timeout=%ld, dest_server=%s", 
                packet_code, timeout, server.to_cstring());
            rc = OB_RESPONSE_TIME_OUT;
          }
          else
          {
            response = dynamic_cast<ObPacket*>(wait_object->get_response());
            // there's two situation on here.
            // 1. connect remote server failed, ControlPacket(timeout) raise up.
            // 2. timeout parameter of this function greater than default timeout
            // of ConnectManager(5000ms), Packet timeout raise up.
            // TODO, maybe need a new error code.
            rc = (NULL !=  response) ? OB_SUCCESS : OB_RESPONSE_TIME_OUT;
          }

        }
        else
        {
          packet->free();
          rc = OB_PACKET_NOT_SENT;
          TBSYS_LOG(WARN, "cannot send packet, maybe send queue is full or disconnect.");
        }

        // do not free the response packet.
        waitmgr_->destroy_wait_object(wait_object);
        wait_object = NULL;

        if (OB_SUCCESS == rc && NULL != response)
        {
          rc = response->deserialize();
          if (OB_SUCCESS != rc)
          {
            TBSYS_LOG(ERROR, "response packet deserialize failed.");
            // cannot free response packet, allocate on thread specific memeory.
            response = NULL;
          }
        }

      } 

      return rc;
    }