func readMPUB(r io.Reader, tmp []byte, topic *nsqd.Topic, maxMessageSize int64, traceEnable bool) ([]*nsqd.Message, []*bytes.Buffer, error) { numMessages, err := readLen(r, tmp) if err != nil { return nil, nil, protocol.NewFatalClientErr(err, "E_BAD_BODY", "MPUB failed to read message count") } if numMessages <= 0 { return nil, nil, protocol.NewFatalClientErr(err, "E_BAD_BODY", fmt.Sprintf("MPUB invalid message count %d", numMessages)) } messages := make([]*nsqd.Message, 0, numMessages) buffers := make([]*bytes.Buffer, 0, numMessages) for i := int32(0); i < numMessages; i++ { messageSize, err := readLen(r, tmp) if err != nil { return nil, buffers, protocol.NewFatalClientErr(err, "E_BAD_MESSAGE", fmt.Sprintf("MPUB failed to read message(%d) body size", i)) } if messageSize <= 0 { return nil, buffers, protocol.NewFatalClientErr(nil, "E_BAD_MESSAGE", fmt.Sprintf("MPUB invalid message(%d) body size %d", i, messageSize)) } if int64(messageSize) > maxMessageSize { return nil, buffers, protocol.NewFatalClientErr(nil, "E_BAD_MESSAGE", fmt.Sprintf("MPUB message too big %d > %d", messageSize, maxMessageSize)) } b := topic.BufferPoolGet(int(messageSize)) buffers = append(buffers, b) _, err = io.CopyN(b, r, int64(messageSize)) if err != nil { return nil, buffers, protocol.NewFatalClientErr(err, "E_BAD_MESSAGE", "MPUB failed to read message body") } msgBody := b.Bytes()[:messageSize] traceID := uint64(0) var realBody []byte if traceEnable { if messageSize <= nsqd.MsgTraceIDLength { return nil, buffers, protocol.NewFatalClientErr(nil, "E_BAD_MESSAGE", fmt.Sprintf("MPUB invalid message(%d) body size %d for tracing", i, messageSize)) } traceID = binary.BigEndian.Uint64(msgBody[:nsqd.MsgTraceIDLength]) realBody = msgBody[nsqd.MsgTraceIDLength:] } else { realBody = msgBody } msg := nsqd.NewMessage(0, realBody) msg.TraceID = traceID messages = append(messages, msg) topic.GetDetailStats().UpdateTopicMsgStats(int64(len(realBody)), 0) } return messages, buffers, nil }