Package com.taobao.metamorphosis.utils

Source Code of com.taobao.metamorphosis.utils.MessageUtils$DecodedMessage

/*
* (C) 2007-2012 Alibaba Group Holding Limited.
*
* 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.
* Authors:
*   wuhua <wq163@163.com> , boyan <killme2008@gmail.com>
*/
package com.taobao.metamorphosis.utils;

import java.nio.ByteBuffer;
import java.util.List;

import com.taobao.metamorphosis.Message;
import com.taobao.metamorphosis.MessageAccessor;
import com.taobao.metamorphosis.exception.InvalidCheckSumException;
import com.taobao.metamorphosis.exception.InvalidMessageException;
import com.taobao.metamorphosis.network.ByteUtils;
import com.taobao.metamorphosis.network.PutCommand;


public final class MessageUtils {

    public final static class DecodedMessage {
        public final int newOffset;
        public final Message message;
        public final ByteBuffer buf;


        public DecodedMessage(final int newOffset, final Message message, final ByteBuffer buf) {
            super();
            this.newOffset = newOffset;
            this.message = message;
            this.buf = buf;
        }

    }


    /**
     * ������Ϣbuffer��ʵ�ʴ洢�ڷ������Ľṹ���£�
     * <ul>
     * <li>message length(4 bytes),including attribute and payload</li>
     * <li>checksum(4 bytes)</li>
     * <li>message id(8 bytes)</li>
     * <li>message flag(4 bytes)</li>
     * <li>attribute length(4 bytes) + attribute,optional</li>
     * <li>payload</li>
     * </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;
    }


    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;
    }


    /**
     * ��binary�����н����Ϣ
     *
     * @param topic
     * @param data
     * @param offset
     * @return
     * @throws InvalidMessageException
     */
    public static final DecodedMessage decodeMessage(final String topic, final byte[] data, final int offset)
            throws InvalidMessageException {
        final ByteBuffer buf = ByteBuffer.wrap(data, offset, HEADER_LEN);
        final int msgLen = buf.getInt();
        final int checksum = buf.getInt();
        vailidateMessage(offset + HEADER_LEN, msgLen, checksum, data);
        final long id = buf.getLong();
        // ȡflag
        final int flag = buf.getInt();
        String attribute = null;
        int payLoadOffset = offset + HEADER_LEN;
        int payLoadLen = msgLen;
        if (payLoadLen > MAX_READ_BUFFER_SIZE) {
            throw new InvalidMessageException("Too much long payload length:" + payLoadLen);
        }
        // ��������ԣ���Ҫ��������
        if (MessageFlagUtils.hasAttribute(flag)) {
            // ȡ4���ֽڵ����Գ���
            final int attrLen = getInt(offset + HEADER_LEN, data);
            // ȡ��Ϣ����
            final byte[] attrData = new byte[attrLen];
            System.arraycopy(data, offset + HEADER_LEN + 4, attrData, 0, attrLen);
            attribute = ByteUtils.getString(attrData);
            // ����payloadOffset������4���ֽڵ���Ϣ���Ⱥ���Ϣ���ȱ���
            payLoadOffset = offset + HEADER_LEN + 4 + attrLen;
            // payload���ȵݼ�����ȥ4���ֽڵ���Ϣ���Ⱥ���Ϣ���ȱ���
            payLoadLen = msgLen - 4 - attrLen;
        }
        // ��ȡpayload
        final byte[] payload = new byte[payLoadLen];
        System.arraycopy(data, payLoadOffset, payload, 0, payLoadLen);
        final Message msg = new Message(topic, payload);
        MessageAccessor.setFlag(msg, flag);
        msg.setAttribute(attribute);
        MessageAccessor.setId(msg, id);
        return new DecodedMessage(payLoadOffset + payLoadLen, msg, ByteBuffer.wrap(data, offset, payLoadOffset
            + payLoadLen - offset));
    }


    /**
     * У��checksum
     *
     * @param msg
     * @param checksum
     */
    public static final void vailidateMessage(final int offset, final int msgLen, final int checksum, final byte[] data)
            throws InvalidMessageException {
        if (checksum != CheckSum.crc32(data, offset, msgLen)) {
            throw new InvalidMessageException("Invalid message");
        }
    }


    public static final int getInt(final int offset, final byte[] data) {
        return ByteBuffer.wrap(data, offset, 4).getInt();
    }

    /**
     * 20���ֽڵ�ͷ�� *
     * <ul>
     * <li>message length(4 bytes),including attribute and payload</li>
     * <li>checksum(4 bytes)</li>
     * <li>message id(8 bytes)</li>
     * <li>message flag(4 bytes)</li>
     * </ul>
     */
    public static final int HEADER_LEN = 20;
    public static final int MAX_READ_BUFFER_SIZE = Integer.parseInt(System.getProperty(
        "notify.remoting.max_read_buffer_size", "2097152"));


    /**
     * ����Ϣ���Ժ���Ϣpayload������ṹ���£�</br></br> 0����1������attribute + payload
     *
     * @param message
     * @return
     */
    public final static byte[] encodePayload(final Message message) {
        final byte[] payload = message.getData();
        final String attribute = message.getAttribute();
        byte[] attrData = null;
        if (attribute != null) {
            attrData = ByteUtils.getBytes(attribute);
        }
        else {
            return payload;
        }
        final int attrLen = attrData == null ? 0 : attrData.length;
        final ByteBuffer buffer = ByteBuffer.allocate(4 + attrLen + payload.length);
        if (attribute != null) {
            buffer.putInt(attrLen);
            if (attrData != null) {
                buffer.put(attrData);
            }
        }

        buffer.put(payload);
        return buffer.array();
    }

}
TOP

Related Classes of com.taobao.metamorphosis.utils.MessageUtils$DecodedMessage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.