private boolean processWhenRetryTooMany(final FetchRequest request, final MessageIterator it) {
      if (SimpleFetchManager.this.isRetryTooMany(request)) {
        try {
          final Message couldNotProecssMsg = it.next();
          MessageAccessor.setPartition(couldNotProecssMsg, request.getPartitionObject());
          MetaStatLog.addStat(null, StatConstants.SKIP_MSG_COUNT, couldNotProecssMsg.getTopic());
          SimpleFetchManager.this.consumer.appendCouldNotProcessMessage(couldNotProecssMsg);
        } catch (final InvalidMessageException e) {
          MetaStatLog.addStat(null, StatConstants.INVALID_MSG_STAT, request.getTopic());
          // 消息体非法,获取有效offset,重新发起查询
          this.getOffsetAddRequest(request, e);
          return true;
        } catch (final Throwable t) {
          this.LogAddRequest(request, t);
          return true;
        }

        request.resetRetries();
        // 跳过这条不能处理的消息
        request.setOffset(request.getOffset() + it.getOffset(), it.getPrevMessage().getId(), true);
        // 强制设置延迟为0
        request.setDelay(0);
        SimpleFetchManager.this.addFetchRequest(request);
        return true;
      } else {
        return false;
      }
    }
 private void ackRequest(
     final FetchRequest request, final MessageIterator it, final boolean ack) {
   request.setOffset(
       request.getOffset() + it.getOffset(),
       it.getPrevMessage() != null ? it.getPrevMessage().getId() : -1,
       ack);
   this.addRequst(request);
 }
    private void postReceiveMessage(
        final FetchRequest request, final MessageIterator it, final Partition partition) {
      // 如果offset仍然没有前进,递增重试次数
      if (it.getOffset() == 0) {
        request.incrementRetriesAndGet();
      } else {
        request.resetRetries();
      }

      // 非自动ack模式
      if (!partition.isAutoAck()) {
        // 如果是回滚,则回滚offset,再次发起请求
        if (partition.isRollback()) {
          request.rollbackOffset();
          partition.reset();
          this.addRequst(request);
        }
        // 如果提交,则更新临时offset到存储
        else if (partition.isAcked()) {
          partition.reset();
          this.ackRequest(request, it, true);
        } else {
          // 都不是,递增临时offset
          this.ackRequest(request, it, false);
        }
      } else {
        // 自动ack模式
        this.ackRequest(request, it, true);
      }
    }
 /**
  * 返回是否需要跳过后续的处理
  *
  * @param request
  * @param it
  * @param listener
  * @param partition
  * @return
  */
 private boolean processReceiveMessage(
     final FetchRequest request,
     final MessageIterator it,
     final MessageListener listener,
     final Partition partition) {
   int count = 0;
   while (it.hasNext()) {
     final int prevOffset = it.getOffset();
     try {
       final Message msg = it.next();
       MessageAccessor.setPartition(msg, partition);
       if (((SimpleMessageConsumer) consumer).canConsumer(msg)) listener.recieveMessages(msg);
       if (partition.isAutoAck()) {
         count++;
       } else {
         // 提交或者回滚都必须跳出循环
         if (partition.isAcked()) {
           count++;
           break;
         } else if (partition.isRollback()) {
           break;
         } else {
           // 不是提交也不是回滚,仅递增计数
           count++;
         }
       }
     } catch (final InvalidMessageException e) {
       MetaStatLog.addStat(null, StatConstants.INVALID_MSG_STAT, request.getTopic());
       // 消息体非法,获取有效offset,重新发起查询
       this.getOffsetAddRequest(request, e);
       return true;
     } catch (final Throwable e) {
       // 将指针移到上一条消息
       it.setOffset(prevOffset);
       log.error(
           "MessageListener处理消息异常,topic="
               + request.getTopic()
               + ",partition="
               + request.getPartition(),
           e);
       // 跳出循环,处理消息异常,到此为止
       break;
     }
   }
   MetaStatLog.addStatValue2(null, StatConstants.GET_MSG_COUNT_STAT, request.getTopic(), count);
   return false;
 }
  public Conversation next() {
    index++;
    if (files == null || files.length <= index) {
      return null;
    }

    for (; index < files.length; index++) {
      File file = files[index];
      if (!file.isFile()) {
        continue;
      }
      try {
        String name = file.getName();
        long uid = Long.parseLong(name);

        RandomAccessFile f = new RandomAccessFile(file, "r");
        MessageIterator iter = new MessageIterator(f);
        IMessage msg = iter.next();
        if (msg == null) {
          continue;
        }
        Conversation conv = new Conversation();
        conv.type = this.type;
        conv.cid = uid;
        conv.message = msg;
        return conv;
      } catch (NumberFormatException e) {
        e.printStackTrace();
        continue;
      } catch (FileNotFoundException e) {
        e.printStackTrace();
        continue;
      } catch (IOException e) {
        e.printStackTrace();
        continue;
      }
    }
    return null;
  }
    /**
     * 处理消息的整个流程:<br>
     *
     * <ul>
     *   <li>1.判断是否有消息可以处理,如果没有消息并且有数据递增重试次数,并判断是否需要递增maxSize
     *   <li>2.判断消息是否重试多次,如果超过设定次数,就跳过该消息继续往下走。跳过的消息可能在本地重试或者交给notify重投
     *   <li>3.进入消息处理流程,根据是否自动ack的情况进行处理:
     *       <ul>
     *         <li>(1)如果消息是自动ack,如果消费发生异常,则不修改offset,延迟消费等待重试
     *         <li>(2)如果消息是自动ack,如果消费正常,递增offset
     *         <li>(3)如果消息非自动ack,如果消费正常并ack,将offset修改为tmp offset,并重设tmp offset
     *         <li>(4)如果消息非自动ack,如果消费正常并rollback,不递增offset,重设tmp offset
     *         <li>(5)如果消息非自动ack,如果消费正常不ack也不rollback,不递增offset,递增tmp offset
     *       </ul>
     * </ul>
     *
     * @param request
     * @param it
     * @param listener
     */
    private void receiveMessages(
        final FetchRequest request, final MessageIterator it, final MessageListener listener) {
      if (it != null && it.hasNext()) {
        if (this.processWhenRetryTooMany(request, it)) {
          return;
        }
        final Partition partition = request.getPartitionObject();
        if (this.processReceiveMessage(request, it, listener, partition)) {
          return;
        }
        this.postReceiveMessage(request, it, partition);
      } else {

        // 尝试多次无法解析出获取的数据,可能需要增大maxSize
        if (SimpleFetchManager.this.isRetryTooManyForIncrease(request)
            && it != null
            && it.getDataLength() > 0) {
          request.increaseMaxSize();
          log.warn(
              "警告,第"
                  + request.getRetries()
                  + "次无法拉取topic="
                  + request.getTopic()
                  + ",partition="
                  + request.getPartitionObject()
                  + "的消息,递增maxSize="
                  + request.getMaxSize()
                  + " Bytes");
        }

        // 一定要判断it是否为null,否则正常的拉到结尾时(返回null)也将进行Retries记数,会导致以后再拉到消息时进入recover
        if (it != null) {
          request.incrementRetriesAndGet();
        }

        this.updateDelay(request);
        SimpleFetchManager.this.addFetchRequest(request);
      }
    }
 public boolean hasNext() {
   try {
     if (folderIter == null) {
       folderIter = new FolderIterator(mailbox);
     }
     // get next message from the folder
     // if folder is exhausted get next folder
     // loop till a valid mail or all folders exhausted.
     while (msgIter == null || !msgIter.hasNext()) {
       Folder next = folderIter.hasNext() ? folderIter.next() : null;
       if (next == null) {
         return false;
       }
       msgIter = new MessageIterator(next, batchSize);
     }
   } catch (EmailFetchException e) {
     LOG.error("Fetching email failed", e);
     return false;
   }
   return true;
 }
 public String getFolder() {
   if (msgIter == null) {
     return null;
   }
   return msgIter.getFolder();
 }
 public IMAPMessage next() {
   return (IMAPMessage) msgIter.next();
 }