All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.liferay.portal.kernel.nio.intraband.Datagram Maven / Gradle / Ivy

There is a newer version: 7.4.3.112-ga112
Show newest version
/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

package com.liferay.portal.kernel.nio.intraband;

import com.liferay.petra.string.StringPool;
import com.liferay.portal.kernel.io.BigEndianCodec;
import com.liferay.portal.kernel.util.StringBundler;

import java.io.EOFException;
import java.io.IOException;

import java.nio.ByteBuffer;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;

import java.util.EnumSet;

/**
 * Represents the communication unit of Intraband.
 *
 * 

* Encodes/decodes data to/from big-endian byte order data format: *

* *

*

* * * * * * * * * * * * * * * * * * * * * *
NameTypeSize(byte)Offset
Status Flagbyte10
Sequence IDlong81
Data Typebyte19
Data Sizeint410
Data Chunkbyte[] *
${Data Size}
14
*

* * @author Shuyang Zhou */ public class Datagram { public static Datagram createRequestDatagram(byte type, byte[] data) { return createRequestDatagram(type, ByteBuffer.wrap(data)); } public static Datagram createRequestDatagram( byte type, ByteBuffer dataByteBuffer) { Datagram datagram = new Datagram(); // Status flag datagram._headerBufferArray[_INDEX_STATUS_FLAG] = _FLAG_REQUEST; // Request datagram does not set the sequence ID // Data type datagram._headerBufferArray[_INDEX_DATA_TYPE] = type; // Data size BigEndianCodec.putInt( datagram._headerBufferArray, _INDEX_DATA_SIZE, dataByteBuffer.remaining()); // Data chunk datagram._dataByteBuffer = dataByteBuffer; return datagram; } public static Datagram createResponseDatagram( Datagram requestDatagram, byte[] data) { return createResponseDatagram(requestDatagram, ByteBuffer.wrap(data)); } public static Datagram createResponseDatagram( Datagram requestDatagram, ByteBuffer byteBuffer) { Datagram datagram = new Datagram(); // Status flag datagram._headerBufferArray[_INDEX_STATUS_FLAG] = _FLAG_RESPONSE; // Sequence ID BigEndianCodec.putLong( datagram._headerBufferArray, _INDEX_SEQUENCE_ID, requestDatagram.getSequenceId()); // Response datagram does not set the data type // Data size BigEndianCodec.putInt( datagram._headerBufferArray, _INDEX_DATA_SIZE, byteBuffer.remaining()); // Data chunk datagram._dataByteBuffer = byteBuffer; return datagram; } public ByteBuffer getDataByteBuffer() { return _dataByteBuffer; } public byte getType() { return _headerBufferArray[_INDEX_DATA_TYPE]; } @Override public String toString() { StringBundler sb = new StringBundler(11); sb.append("{dataChunk="); ByteBuffer byteBuffer = _dataByteBuffer; if (byteBuffer == null) { sb.append(StringPool.NULL); } else { sb.append(byteBuffer.toString()); } sb.append(", dataSize="); sb.append(BigEndianCodec.getInt(_headerBufferArray, _INDEX_DATA_SIZE)); sb.append(", dataType="); sb.append(_headerBufferArray[_INDEX_DATA_TYPE]); sb.append(", sequenceId="); sb.append( BigEndianCodec.getLong(_headerBufferArray, _INDEX_SEQUENCE_ID)); sb.append(", statusFlag="); sb.append(_headerBufferArray[_INDEX_STATUS_FLAG]); sb.append("}"); return sb.toString(); } protected static Datagram createACKResponseDatagram(long sequenceId) { Datagram datagram = new Datagram(); // Status flag datagram._headerBufferArray[_INDEX_STATUS_FLAG] = _FLAG_ACK_RESPONSE; // Sequence ID BigEndianCodec.putLong( datagram._headerBufferArray, _INDEX_SEQUENCE_ID, sequenceId); // ACK response datagram does not set the data type // Data size BigEndianCodec.putInt(datagram._headerBufferArray, _INDEX_DATA_SIZE, 0); // Data chunk datagram._dataByteBuffer = _EMPTY_BUFFER; return datagram; } protected static Datagram createReceiveDatagram() { return new Datagram(); } protected long getSequenceId() { return BigEndianCodec.getLong(_headerBufferArray, _INDEX_SEQUENCE_ID); } protected boolean isAckRequest() { byte statusFlag = _headerBufferArray[_INDEX_STATUS_FLAG]; if ((statusFlag & _FLAG_ACK_REQUEST) != 0) { return true; } return false; } protected boolean isAckResponse() { byte statusFlag = _headerBufferArray[_INDEX_STATUS_FLAG]; if ((statusFlag & _FLAG_ACK_RESPONSE) != 0) { return true; } return false; } protected boolean isRequest() { byte statusFlag = _headerBufferArray[_INDEX_STATUS_FLAG]; if ((statusFlag & _FLAG_REQUEST) != 0) { return true; } return false; } protected boolean isResponse() { byte statusFlag = _headerBufferArray[_INDEX_STATUS_FLAG]; if ((statusFlag & _FLAG_RESPONSE) != 0) { return true; } return false; } protected boolean readFrom(ScatteringByteChannel scatteringByteChannel) throws IOException { if (_headerByteBuffer.hasRemaining()) { if (scatteringByteChannel.read(_headerByteBuffer) == -1) { throw new EOFException(); } if (_headerByteBuffer.hasRemaining()) { return false; } int dataSize = BigEndianCodec.getInt( _headerBufferArray, _INDEX_DATA_SIZE); if (dataSize == 0) { _dataByteBuffer = _EMPTY_BUFFER; return true; } _dataByteBuffer = ByteBuffer.allocate(dataSize); } if (scatteringByteChannel.read(_dataByteBuffer) == -1) { throw new EOFException(); } if (_dataByteBuffer.hasRemaining()) { return false; } _dataByteBuffer.flip(); return true; } protected void setAckRequest(boolean ackRequest) { byte statusFlag = _headerBufferArray[_INDEX_STATUS_FLAG]; if (ackRequest) { statusFlag |= _FLAG_ACK_REQUEST; } else { statusFlag &= ~_FLAG_ACK_REQUEST; } _headerBufferArray[_INDEX_STATUS_FLAG] = statusFlag; } protected void setSequenceId(long sequenceId) { BigEndianCodec.putLong( _headerBufferArray, _INDEX_SEQUENCE_ID, sequenceId); } protected boolean writeTo(GatheringByteChannel gatheringByteChannel) throws IOException { if (_headerByteBuffer.hasRemaining()) { ByteBuffer[] byteBuffers = new ByteBuffer[2]; byteBuffers[0] = _headerByteBuffer; byteBuffers[1] = _dataByteBuffer; gatheringByteChannel.write(byteBuffers); } else { gatheringByteChannel.write(_dataByteBuffer); } if (_dataByteBuffer.hasRemaining()) { return false; } _dataByteBuffer = null; return true; } protected Object attachment; protected CompletionHandler completionHandler; protected EnumSet completionTypes; protected long expireTime; protected long timeout; private Datagram() { _headerByteBuffer = ByteBuffer.allocate(_HEADER_SIZE); // Directly reference the interanl byte array for faster encoding and // decoding _headerBufferArray = _headerByteBuffer.array(); } private static final ByteBuffer _EMPTY_BUFFER = ByteBuffer.allocate(0); private static final byte _FLAG_ACK_REQUEST = 1; private static final byte _FLAG_ACK_RESPONSE = 2; private static final byte _FLAG_REQUEST = 4; private static final byte _FLAG_RESPONSE = 8; private static final int _HEADER_SIZE = 14; private static final int _INDEX_DATA_SIZE = 10; private static final int _INDEX_DATA_TYPE = 9; private static final int _INDEX_SEQUENCE_ID = 1; private static final int _INDEX_STATUS_FLAG = 0; private ByteBuffer _dataByteBuffer; private final byte[] _headerBufferArray; private final ByteBuffer _headerByteBuffer; }