qunar.tc.qmq.protocol.MessagesPayloadHolder.java Source code

Java tutorial

Introduction

Here is the source code for qunar.tc.qmq.protocol.MessagesPayloadHolder.java

Source

/*
 * Copyright 2018 Qunar, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package qunar.tc.qmq.protocol;

import io.netty.buffer.ByteBuf;
import qunar.tc.qmq.base.BaseMessage;
import qunar.tc.qmq.utils.Crc32;
import qunar.tc.qmq.utils.DelayUtil;
import qunar.tc.qmq.utils.Flags;
import qunar.tc.qmq.utils.PayloadHolderUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Created by zhaohui.yu
 * 7/21/17
 */
public class MessagesPayloadHolder implements PayloadHolder {
    private final List<BaseMessage> messages;

    public MessagesPayloadHolder(List<BaseMessage> messages) {
        this.messages = messages;
    }

    @Override
    public void writeBody(ByteBuf out) {
        if (messages == null || messages.size() == 0)
            return;
        for (BaseMessage message : messages) {
            serializeMessage(message, out);
        }
    }

    private void serializeMessage(BaseMessage message, ByteBuf out) {
        int crcIndex = out.writerIndex();
        // sizeof(bodyCrc<long>)
        out.ensureWritable(8);
        out.writerIndex(crcIndex + 8);

        final int messageStart = out.writerIndex();

        // flag
        byte flag = 0;
        //?(1)?(0)?(1)?(0)?Tag
        flag = Flags.setDelay(flag, DelayUtil.isDelayMessage(message));

        //in avoid add tag after sendMessage
        Set<String> tags = new HashSet<>(message.getTags());
        flag = Flags.setTags(flag, hasTags(tags));

        out.writeByte(flag);

        // created time
        out.writeLong(message.getCreatedTime().getTime());
        if (Flags.isDelay(flag)) {
            out.writeLong(message.getScheduleReceiveTime().getTime());
        } else {
            // expired time
            out.writeLong(System.currentTimeMillis());
        }
        // subject
        PayloadHolderUtils.writeString(message.getSubject(), out);
        // message id
        PayloadHolderUtils.writeString(message.getMessageId(), out);

        writeTags(tags, out);

        out.markWriterIndex();
        // writerIndex + sizeof(bodyLength<int>)
        final int bodyStart = out.writerIndex() + 4;
        out.ensureWritable(4);
        out.writerIndex(bodyStart);

        serializeMap(message.getAttrs(), out);
        final int bodyEnd = out.writerIndex();

        final int messageEnd = out.writerIndex();

        final int bodyLen = bodyEnd - bodyStart;
        final int messageLength = bodyEnd - messageStart;

        // write body length
        out.resetWriterIndex();
        out.writeInt(bodyLen);

        // write message crc
        out.writerIndex(crcIndex);
        out.writeLong(messageCrc(out, messageStart, messageLength));

        out.writerIndex(messageEnd);
    }

    private void writeTags(Set<String> tags, ByteBuf out) {
        if (tags.isEmpty())
            return;
        out.writeByte((byte) tags.size());
        for (final String tag : tags) {
            PayloadHolderUtils.writeString(tag, out);
        }
    }

    private boolean hasTags(Set<String> tags) {
        return tags.size() > 0;
    }

    //TODO: ?
    private void serializeMap(Map<String, Object> map, ByteBuf out) {
        if (null == map || map.isEmpty())
            return;

        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (entry.getKey() == null || entry.getValue() == null)
                continue;
            PayloadHolderUtils.writeString(entry.getKey(), out);
            PayloadHolderUtils.writeString(entry.getValue().toString(), out);
        }
    }

    private long messageCrc(ByteBuf out, int messageStart, int messageLength) {
        return Crc32.crc32(out.nioBuffer(messageStart, messageLength), 0, messageLength);
    }
}