Пример #1
0
    public AppendMessageResult doAppend(
        final long fileFromOffset,
        final ByteBuffer byteBuffer,
        final int maxBlank,
        final Object msg) {
      /** 生成消息ID STORETIMESTAMP + STOREHOSTADDRESS + OFFSET <br> */
      MessageExtBrokerInner msgInner = (MessageExtBrokerInner) msg;
      // PHY OFFSET
      long wroteOffset = fileFromOffset + byteBuffer.position();
      String msgId =
          MessageDecoder.createMessageId(
              this.msgIdMemory, msgInner.getStoreHostBytes(), wroteOffset);

      /** 记录ConsumeQueue信息 */
      String key = msgInner.getTopic() + "-" + msgInner.getQueueId();
      Long queueOffset = CommitLog.this.topicQueueTable.get(key);
      if (null == queueOffset) {
        queueOffset = 0L;
        CommitLog.this.topicQueueTable.put(key, queueOffset);
      }

      /** 事务消息需要特殊处理 */
      final int tranType = MessageSysFlag.getTransactionValue(msgInner.getSysFlag());
      switch (tranType) {
        case MessageSysFlag.TransactionPreparedType:
          queueOffset =
              CommitLog.this
                  .defaultMessageStore
                  .getTransactionStateService()
                  .getTranStateTableOffset()
                  .get();
          break;
        case MessageSysFlag.TransactionRollbackType:
          queueOffset = msgInner.getQueueOffset();
          break;
        case MessageSysFlag.TransactionNotType:
        case MessageSysFlag.TransactionCommitType:
        default:
          break;
      }

      /** 序列化消息 */
      final byte[] propertiesData =
          msgInner.getPropertiesString() == null ? null : msgInner.getPropertiesString().getBytes();
      final int propertiesLength = propertiesData == null ? 0 : propertiesData.length;

      final byte[] topicData = msgInner.getTopic().getBytes();
      final int topicLength = topicData == null ? 0 : topicData.length;

      final int bodyLength = msgInner.getBody() == null ? 0 : msgInner.getBody().length;

      final int msgLen =
          4 // 1 TOTALSIZE
              + 4 // 2 MAGICCODE
              + 4 // 3 BODYCRC
              + 4 // 4 QUEUEID
              + 4 // 5 FLAG
              + 8 // 6 QUEUEOFFSET
              + 8 // 7 PHYSICALOFFSET
              + 4 // 8 SYSFLAG
              + 8 // 9 BORNTIMESTAMP
              + 8 // 10 BORNHOST
              + 8 // 11 STORETIMESTAMP
              + 8 // 12 STOREHOSTADDRESS
              + 4 // 13 RECONSUMETIMES
              + 8 // 14 Prepared Transaction Offset
              + 4
              + bodyLength // 14 BODY
              + 1
              + topicLength // 15 TOPIC
              + 2
              + propertiesLength // 16 propertiesLength
              + 0;

      // 消息超过设定的最大值
      if (msgLen > this.maxMessageSize) {
        CommitLog.log.warn(
            "message size exceeded, msg total size: "
                + msgLen
                + ", msg body size: "
                + bodyLength
                + ", maxMessageSize: "
                + this.maxMessageSize);
        return new AppendMessageResult(AppendMessageStatus.MESSAGE_SIZE_EXCEEDED);
      }

      // 判断是否有足够空余空间
      if ((msgLen + END_FILE_MIN_BLANK_LENGTH) > maxBlank) {
        this.resetMsgStoreItemMemory(maxBlank);
        // 1 TOTALSIZE
        this.msgStoreItemMemory.putInt(maxBlank);
        // 2 MAGICCODE
        this.msgStoreItemMemory.putInt(CommitLog.BlankMagicCode);
        // 3 剩余空间可能是任何值
        //

        // 此处长度特意设置为maxBlank
        byteBuffer.put(this.msgStoreItemMemory.array(), 0, maxBlank);
        return new AppendMessageResult(
            AppendMessageStatus.END_OF_FILE,
            wroteOffset,
            maxBlank,
            msgId,
            msgInner.getStoreTimestamp(),
            queueOffset);
      }

      // 初始化存储空间
      this.resetMsgStoreItemMemory(msgLen);
      // 1 TOTALSIZE
      this.msgStoreItemMemory.putInt(msgLen);
      // 2 MAGICCODE
      this.msgStoreItemMemory.putInt(CommitLog.MessageMagicCode);
      // 3 BODYCRC
      this.msgStoreItemMemory.putInt(msgInner.getBodyCRC());
      // 4 QUEUEID
      this.msgStoreItemMemory.putInt(msgInner.getQueueId());
      // 5 FLAG
      this.msgStoreItemMemory.putInt(msgInner.getFlag());
      // 6 QUEUEOFFSET
      this.msgStoreItemMemory.putLong(queueOffset);
      // 7 PHYSICALOFFSET
      this.msgStoreItemMemory.putLong(fileFromOffset + byteBuffer.position());
      // 8 SYSFLAG
      this.msgStoreItemMemory.putInt(msgInner.getSysFlag());
      // 9 BORNTIMESTAMP
      this.msgStoreItemMemory.putLong(msgInner.getBornTimestamp());
      // 10 BORNHOST
      this.msgStoreItemMemory.put(msgInner.getBornHostBytes());
      // 11 STORETIMESTAMP
      this.msgStoreItemMemory.putLong(msgInner.getStoreTimestamp());
      // 12 STOREHOSTADDRESS
      this.msgStoreItemMemory.put(msgInner.getStoreHostBytes());
      // 13 RECONSUMETIMES
      this.msgStoreItemMemory.putInt(msgInner.getReconsumeTimes());
      // 14 Prepared Transaction Offset
      this.msgStoreItemMemory.putLong(msgInner.getPreparedTransactionOffset());
      // 15 BODY
      this.msgStoreItemMemory.putInt(bodyLength);
      if (bodyLength > 0) this.msgStoreItemMemory.put(msgInner.getBody());
      // 16 TOPIC
      this.msgStoreItemMemory.put((byte) topicLength);
      this.msgStoreItemMemory.put(topicData);
      // 17 PROPERTIES
      this.msgStoreItemMemory.putShort((short) propertiesLength);
      if (propertiesLength > 0) this.msgStoreItemMemory.put(propertiesData);

      // 向队列缓冲区写入消息
      byteBuffer.put(this.msgStoreItemMemory.array(), 0, msgLen);

      AppendMessageResult result =
          new AppendMessageResult(
              AppendMessageStatus.PUT_OK,
              wroteOffset,
              msgLen,
              msgId,
              msgInner.getStoreTimestamp(),
              queueOffset);

      switch (tranType) {
        case MessageSysFlag.TransactionPreparedType:
          CommitLog.this
              .defaultMessageStore
              .getTransactionStateService()
              .getTranStateTableOffset()
              .incrementAndGet();
          break;
        case MessageSysFlag.TransactionRollbackType:
          break;
        case MessageSysFlag.TransactionNotType:
        case MessageSysFlag.TransactionCommitType:
          // 更新下一次的ConsumeQueue信息
          CommitLog.this.topicQueueTable.put(key, ++queueOffset);
          break;
        default:
          break;
      }

      // 返回结果
      return result;
    }