/** 添加消息,为了保证添加顺序,这里不得不加锁 */
 @Override
 public void addMessage(
     final MessageStore store, final long msgId, final PutCommand putCmd, JournalLocation location)
     throws IOException {
   if (location == null) {
     // 非重放,添加put日志
     final AppendMessageCommand appendCmd =
         AppendMessageCommand.newBuilder()
             .setMessageId(msgId)
             .setPutCommand(ByteString.copyFrom(putCmd.encode().array()))
             .build();
     final TxCommand txCommand =
         TxCommand.newBuilder()
             .setCmdType(TxCommandType.APPEND_MSG)
             .setCmdContent(appendCmd.toByteString())
             .build();
     final Tx tx = this.getInflyTx(putCmd.getTransactionId());
     if (tx != null) {
       location = this.journalStore.write(txCommand, null, tx.location, false);
     } else {
       location = this.journalStore.write(txCommand, null, null, false);
     }
   }
   final Tx tx = this.getTx(putCmd.getTransactionId(), location);
   tx.add(store, msgId, putCmd);
 }
 public static final ByteBuffer makeMessageBuffer(
     final List<Long> msgIds, final List<PutCommand> reqs) {
   if (msgIds == null || reqs == null) {
     throw new IllegalArgumentException("Null id list or request list");
   }
   if (msgIds.size() != reqs.size()) {
     throw new IllegalArgumentException("id list is not adapte to request list");
   }
   int capacity = 0;
   for (final PutCommand req : reqs) {
     capacity += 4 + 4 + 8 + 4 + req.getData().length;
   }
   final ByteBuffer buffer = ByteBuffer.allocate(capacity);
   for (int i = 0; i < reqs.size(); i++) {
     final PutCommand req = reqs.get(i);
     final long msgId = msgIds.get(i);
     buffer.putInt(req.getData().length);
     buffer.putInt(CheckSum.crc32(req.getData()));
     buffer.putLong(msgId);
     buffer.putInt(req.getFlag());
     buffer.put(req.getData());
   }
   buffer.flip();
   return buffer;
 }
 /**
  * 创建消息buffer,实际存储在服务器的结构如下:
  *
  * <ul>
  *   <li>message length(4 bytes),including attribute and payload
  *   <li>checksum(4 bytes)
  *   <li>message id(8 bytes)
  *   <li>message flag(4 bytes)
  *   <li>attribute length(4 bytes) + attribute,optional
  *   <li>payload
  * </ul>
  *
  * @param req
  * @return
  */
 public static final ByteBuffer makeMessageBuffer(final long msgId, final PutCommand req) {
   // message length + checksum + id +flag + data
   final ByteBuffer buffer = ByteBuffer.allocate(4 + 4 + 8 + 4 + req.getData().length);
   buffer.putInt(req.getData().length);
   int checkSum = CheckSum.crc32(req.getData());
   // If client passes checksum,compare them
   if (req.getCheckSum() != -1) {
     if (checkSum != req.getCheckSum()) {
       throw new InvalidCheckSumException(
           "Checksum failure,message may be corrupted when transfering on networking.");
     }
   }
   buffer.putInt(checkSum);
   buffer.putLong(msgId);
   buffer.putInt(req.getFlag());
   buffer.put(req.getData());
   buffer.flip();
   return buffer;
 }