public void processPubRec(ServerChannel session, PubRecMessage msg) {
    String clientID = (String) session.getAttribute(NettyChannel.ATTR_KEY_CLIENTID);
    int messageID = msg.getMessageID();
    ClientSession targetSession = m_sessionsStore.sessionForClient(clientID);
    verifyToActivate(clientID, targetSession);
    // remove from the inflight and move to the QoS2 second phase queue
    targetSession.inFlightAcknowledged(messageID);
    targetSession.secondPhaseAckWaiting(messageID);
    // once received a PUBREC reply with a PUBREL(messageID)
    LOG.debug(
        "\t\tSRV <--PUBREC-- SUB processPubRec invoked for clientID {} ad messageID {}",
        clientID,
        messageID);
    PubRelMessage pubRelMessage = new PubRelMessage();
    pubRelMessage.setMessageID(messageID);
    pubRelMessage.setQos(AbstractMessage.QOSType.LEAST_ONE);

    session.write(pubRelMessage);
  }
  /**
   * Second phase of a publish QoS2 protocol, sent by publisher to the broker. Search the stored
   * message and publish to all interested subscribers.
   */
  public void processPubRel(ServerChannel session, PubRelMessage msg) {
    String clientID = (String) session.getAttribute(NettyChannel.ATTR_KEY_CLIENTID);
    int messageID = msg.getMessageID();
    LOG.debug(
        "PUB --PUBREL--> SRV processPubRel invoked for clientID {} ad messageID {}",
        clientID,
        messageID);
    ClientSession targetSession = m_sessionsStore.sessionForClient(clientID);
    verifyToActivate(clientID, targetSession);
    IMessagesStore.StoredMessage evt = targetSession.storedMessage(messageID);
    route2Subscribers(evt);

    if (evt.isRetained()) {
      final String topic = evt.getTopic();
      if (!evt.getMessage().hasRemaining()) {
        m_messagesStore.cleanRetained(topic);
      } else {
        m_messagesStore.storeRetained(topic, evt.getGuid());
      }
    }

    sendPubComp(clientID, messageID);
  }